classifyApiError function

ApiError classifyApiError({
  1. required int statusCode,
  2. required String body,
  3. String? retryAfterHeader,
})

Classify an HTTP error response into an ApiError.

Implementation

ApiError classifyApiError({
  required int statusCode,
  required String body,
  String? retryAfterHeader,
}) {
  // Rate limit
  if (statusCode == 429) {
    return ApiError(
      type: ApiErrorType.rateLimited,
      message: 'Rate limited. Please wait before retrying.',
      statusCode: statusCode,
      retryAfter: retryAfterHeader,
    );
  }

  // Overloaded
  if (statusCode == 529) {
    return ApiError(
      type: ApiErrorType.overloaded,
      message: 'API is overloaded. Retrying...',
      statusCode: statusCode,
      retryAfter: retryAfterHeader,
    );
  }

  // Auth
  if (statusCode == 401) {
    return ApiError(
      type: ApiErrorType.authenticationError,
      message: 'Invalid API key or authentication failed.',
      statusCode: statusCode,
    );
  }

  if (statusCode == 403) {
    return ApiError(
      type: ApiErrorType.permissionDenied,
      message: 'Permission denied. Check your API key permissions.',
      statusCode: statusCode,
    );
  }

  // Bad request — check for specific sub-types
  if (statusCode == 400) {
    final lowerBody = body.toLowerCase();

    // Prompt too long
    if (lowerBody.contains('prompt is too long') ||
        lowerBody.contains('max_tokens') && lowerBody.contains('exceed')) {
      final tokenGap = _parseTokenGap(body);
      return ApiError(
        type: ApiErrorType.promptTooLong,
        message: promptTooLongErrorMessage,
        statusCode: statusCode,
        tokenGap: tokenGap,
      );
    }

    // Media size errors
    if (lowerBody.contains('image') && lowerBody.contains('size') ||
        lowerBody.contains('pdf') && lowerBody.contains('size')) {
      return ApiError(
        type: ApiErrorType.mediaTooLarge,
        message: 'Image or PDF exceeds size limits.',
        statusCode: statusCode,
      );
    }

    // Tool use errors
    if (lowerBody.contains('tool_use') || lowerBody.contains('tool use')) {
      return ApiError(
        type: ApiErrorType.invalidToolUse,
        message: 'Invalid tool use parameters.',
        statusCode: statusCode,
      );
    }

    return ApiError(
      type: ApiErrorType.invalidRequest,
      message: 'Invalid request: $body',
      statusCode: statusCode,
    );
  }

  // Server errors
  if (statusCode >= 500) {
    return ApiError(
      type: ApiErrorType.serverError,
      message: 'Server error ($statusCode). Retrying...',
      statusCode: statusCode,
    );
  }

  return ApiError(
    type: ApiErrorType.unknown,
    message: 'Unexpected error ($statusCode): $body',
    statusCode: statusCode,
  );
}