Skip to content

feat: Raise API errors as exceptions instead of text messages#526

Draft
wingding12 wants to merge 1 commit intoanthropics:mainfrom
wingding12:fix/api-errors-as-exceptions-472
Draft

feat: Raise API errors as exceptions instead of text messages#526
wingding12 wants to merge 1 commit intoanthropics:mainfrom
wingding12:fix/api-errors-as-exceptions-472

Conversation

@wingding12
Copy link

Summary

This PR addresses issue #472 by converting API error responses into proper Python exceptions that can be caught and handled programmatically.

Problem:
Previously, API errors (rate limits, authentication failures, invalid requests, server errors) were returned as text content within AssistantMessage objects. This made it difficult to distinguish them from normal responses and handle them appropriately in application code.

Solution:

  • Added new exception hierarchy in _errors.py:
    • APIError (base class for all API errors)
    • AuthenticationError (401 responses)
    • BillingError (billing issues)
    • RateLimitError (429 responses)
    • InvalidRequestError (400 responses)
    • ServerError (500/529 responses)
  • Modified _internal/client.py to detect AssistantMessage objects with the error field set and raise the corresponding exception
  • Exported new exception types from __init__.py for public use
  • Added comprehensive tests for all error types and client behavior

Changes:

  • src/claude_agent_sdk/_errors.py - Added 6 new exception types with proper inheritance and attributes
  • src/claude_agent_sdk/_internal/client.py - Added error detection and exception raising logic
  • src/claude_agent_sdk/__init__.py - Exported new exception types
  • tests/test_errors.py - Added tests for new exception types
  • tests/test_client.py - Added tests for error handling in the client

Example Usage

Users can now handle API errors idiomatically:

from claude_agent_sdk import RateLimitError, InvalidRequestError, APIError

try:
    async for msg in query(prompt="Hello"):
        print(msg)
except RateLimitError as e:
    # Implement retry logic with backoff
    print(f"Rate limited: {e}")
except InvalidRequestError as e:
    # Fix request parameters
    print(f"Invalid request: {e}")
except APIError as e:
    # Catch any other API error
    print(f"API error ({e.error_type}): {e}")

Test Plan

  • All existing tests pass (143 tests)
  • New tests added for all exception types
  • New tests added for client error detection
  • Ruff linting passes
  • MyPy type checking passes
  • Normal messages without errors are yielded correctly (no false positives)

Fixes #472

…sages

API errors from the Anthropic API (400, 401, 429, 529, etc.) were being
returned as text messages in AssistantMessage.content instead of being
raised as exceptions. This made it impossible to programmatically handle
API errors with try/except.

Changes:

1. Added new exception hierarchy in _errors.py:
   - APIError (base class with error_type and model attributes)
   - AuthenticationError (authentication_failed)
   - BillingError (billing_error)
   - RateLimitError (rate_limit)
   - InvalidRequestError (invalid_request)
   - ServerError (server_error)

2. Modified message_parser.py to:
   - Read error field from correct location (top level, not nested)
     Fixes anthropics#505
   - Raise appropriate exception when error field is present
     Fixes anthropics#472

3. Added comprehensive tests (27 new tests) covering:
   - Exception class attributes and inheritance
   - Error type to exception class mapping
   - Message parser behavior for each error type
   - Integration patterns (retry logic, catch-all)

Fixes anthropics#472
Fixes anthropics#505
@wingding12 wingding12 force-pushed the fix/api-errors-as-exceptions-472 branch from a453834 to 38c63a0 Compare January 29, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] API errors are returned as text messages instead of raised as exceptions

1 participant