Skip to content

Errors

Every error raised by the SDK descends from ComplianceClientError. HTTP failures live under APIError (with a typed subclass per status code); transport-level failures live under APIConnectionError.

exceptions

Exception hierarchy for the Anthropic Compliance SDK.

All errors raised by claude_compliance_sdk derive from ComplianceClientError. The tree separates HTTP failures (everything under APIError) from transport-level failures (everything under APIConnectionError) so callers can catch the two cases independently.

The Compliance API returns errors in a single JSON shape::

{"error": {"type": "...", "message": "..."}}

Each APIError instance carries the HTTP status code, the request-id response header, the server's error.type and error.message parsed from the body, and the raw decoded body. Use from_response from the transport layer to build the right subclass from an HTTP response.

The server is the source of truth — the client only labels. A 401 is an invalid or revoked key (InvalidAPIKeyError). Scope failures come back as 403 permission_error; the client refines those into InsufficientScopeError (a subclass of PermissionDeniedError) by matching error.type or a scope/permission hint in the message.

Example
from claude_compliance_sdk import (
    ComplianceClient,
    InsufficientScopeError,
    RateLimitError,
)

try:
    ComplianceClient(api_key="sk-ant-api01-...").activities.list()
except InsufficientScopeError as exc:
    print("missing scope:", exc.error_message)
except RateLimitError as exc:
    print("retry after", exc.retry_after, "seconds")

ComplianceClientError

Bases: Exception

Base class for every error raised by the SDK.

Catch this to handle any SDK-originated failure regardless of whether the cause was an HTTP response or a transport-level problem.

APIError

Bases: ComplianceClientError

Error returned by the Compliance API as a non-2xx HTTP response.

Attributes:

Name Type Description
status_code int

HTTP status code from the response.

request_id str | None

Value of the request-id response header, if any. Use this when filing support tickets.

error_type str | None

Server-supplied error.type string (for example authentication_error), if the body matched the expected shape.

error_message str | None

Server-supplied error.message string, if the body matched the expected shape.

body Any

The decoded response body. Typically a dict, but may be str or bytes if the body was not JSON.

from_response classmethod

from_response(
    *,
    status_code: int,
    headers: Mapping[str, str] | None = None,
    body: Any = None
) -> "APIError"

Build the right APIError subclass from a response.

Routes by status code, parses error.type / error.message out of the body when present, lifts request-id from headers, and on 429 parses Retry-After into seconds.

Parameters:

Name Type Description Default
status_code int

HTTP status code from the response.

required
headers Mapping[str, str] | None

Response headers, case-insensitive mapping preferred (httpx.Headers works). Used to read request-id and, for 429, Retry-After.

None
body Any

Decoded response body. dict is preferred so the error.type and error.message fields can be extracted; any other type is stored verbatim and the parsed fields stay None.

None

Returns:

Type Description
'APIError'

An APIError subclass instance matching the status

'APIError'

code. 401 is split between InvalidAPIKeyError and

'APIError'

InsufficientScopeError; 429 returns a

'APIError'

RateLimitError with retry_after populated.

BadRequestError

Bases: APIError

HTTP 400 — request was malformed or violated input constraints.

AuthenticationError

Bases: APIError

HTTP 401 — the request was not authenticated.

The only documented 401 body is an invalid or revoked key, surfaced as InvalidAPIKeyError. Scope failures are not 401s — the API returns those as 403 (see InsufficientScopeError).

InvalidAPIKeyError

Bases: AuthenticationError

HTTP 401 where the API key itself is invalid or revoked.

InsufficientScopeError

Bases: PermissionDeniedError

HTTP 403 where the key is valid but lacks a required scope.

The Compliance API returns scope failures as 403 with error.type: "permission_error". Catch PermissionDeniedError to handle any 403, or this class for the scope-specific case.

PermissionDeniedError

Bases: APIError

HTTP 403 — the caller is authenticated but not permitted.

NotFoundError

Bases: APIError

HTTP 404 — the addressed resource does not exist.

ConflictError

Bases: APIError

HTTP 409 — request conflicts with current server state.

Raised, for example, when deleting a project that still has chats attached.

RateLimitError

Bases: APIError

HTTP 429 — the server-side rate limit (600 RPM) was exceeded.

Attributes:

Name Type Description
retry_after float | None

Seconds to wait before retrying, parsed from the Retry-After response header. None when the server did not supply one. HTTP-date values are converted to a non-negative seconds delta from the current time.

APIStatusError

Bases: APIError

A 4xx status code outside the explicitly modelled set.

InternalServerError

Bases: APIError

HTTP 5xx — the server failed to handle the request.

APIConnectionError

Bases: ComplianceClientError

The request could not reach the server or the response was lost.

Wraps DNS failures, TCP/TLS errors, and any other transport-level fault raised by the underlying HTTP client.

APITimeoutError

Bases: APIConnectionError

The request exceeded the configured per-request timeout.

FileTooLargeError

Bases: ComplianceClientError

Eager download exceeded the configured max_download_bytes cap.

Raised by download, download, and download when the response's Content-Length (or the streamed byte total) exceeds the client's max_download_bytes. Use the streamed alternatives (download_to_file or download_stream) when you genuinely want to fetch something larger than the eager cap.

Attributes:

Name Type Description
size_bytes int | None

Reported file size in bytes, when the server supplied a Content-Length we could compare against the cap. None when the cap was tripped mid-stream because no Content-Length was sent.

max_bytes int

The configured max_download_bytes ceiling.