Skip to content

pydantic_ai.exceptions

PydanticAIDeprecationWarning

Bases: UserWarning

Warning emitted when a deprecated Pydantic AI API is used.

Inherits from UserWarning instead of DeprecationWarning so that deprecations are visible by default at runtime, following the approach described in https://sethmlarson.dev/deprecations-via-warnings-dont-work-for-python-libraries.

CostCalculationFailedWarning

Bases: Warning

Warning raised when cost calculation fails.

UsageExtractionFailedWarning

Bases: Warning

Warning raised when usage extraction fails.

CostNotFoundWarning

Bases: Warning

Warning raised when cost is not found.

UsageLimitUnavailableWarning

Bases: Warning

Warning raised when some responses omit usage while a token or cost limit is configured.

ModelRetry

Bases: Exception

Exception to raise to request a model retry.

Can be raised from tool functions, output validators, and capability hooks (such as after_model_request, after_tool_execute, etc.) to send a retry prompt back to the model asking it to try again.

For a terminal failure the model should see but not retry, raise ToolFailed instead.

Attributes

message

The message to return to the model.

Type: str Default: message

Methods

__get_pydantic_core_schema__

@classmethod

def __get_pydantic_core_schema__(cls, _: Any, __: Any) -> core_schema.CoreSchema

Pydantic core schema to allow ModelRetry to be (de)serialized.

Returns

core_schema.CoreSchema

ToolFailed

Bases: Exception

Exception to raise to report a terminal tool failure to the model.

Raise this when a tool call is done and has failed — a missing resource, an unsupported operation, a definitive upstream error — and you want the model to see the failure and adapt rather than try the same call again. Can be raised from tool functions, args validators, and tool validation/execution hooks.

Like ModelRetry, this produces a failed tool result the model sees; unlike ModelRetry it does not prepend retry/correction instructions and does not consume the tool’s retry budget. Bound repeated failures with UsageLimits at the run level instead.

Attributes

message

The failure message to return to the model.

Type: str Default: message

Methods

__get_pydantic_core_schema__

@classmethod

def __get_pydantic_core_schema__(cls, _: Any, __: Any) -> core_schema.CoreSchema

Pydantic core schema to allow ToolFailed to be (de)serialized.

Returns

core_schema.CoreSchema

CallDeferred

Bases: Exception

Exception to raise when a tool call should be deferred.

See tools docs for more information.

Constructor Parameters

metadata : dict[str, Any] | None Default: None

Optional dictionary of metadata to attach to the deferred tool call. This metadata will be available in DeferredToolRequests.metadata keyed by tool_call_id.

ApprovalRequired

Bases: Exception

Exception to raise when a tool call requires human-in-the-loop approval.

See tools docs for more information.

Constructor Parameters

metadata : dict[str, Any] | None Default: None

Optional dictionary of metadata to attach to the deferred tool call. This metadata will be available in DeferredToolRequests.metadata keyed by tool_call_id.

SkipModelRequest

Bases: Exception

Exception to raise in before/wrap model request hooks to skip the model call.

The provided response will be used instead of calling the model.

Note: when raised in before_model_request, any message history modifications made by earlier capabilities in that hook will not be persisted to the agent’s message history, since the request preparation is aborted.

SkipToolValidation

Bases: Exception

Exception to raise in before/wrap tool validate hooks to skip validation.

The provided args will be used as the validated arguments.

SkipToolExecution

Bases: Exception

Exception to raise in before/wrap tool execute hooks to skip execution.

The provided result will be used as the tool result.

UserError

Bases: RuntimeError

Error caused by a usage mistake by the application developer — You!

Attributes

message

Description of the mistake.

Type: str Default: message

UndrainedPendingMessagesError

Bases: UserError

Error that used to be raised when an agent run ended with messages still queued via enqueue.

A bare async for node in agent_run loop used to skip the node hooks, so 'when_idle' messages and end-of-run redirects (which drain in after_node_run) were stranded. Bare iteration now advances through AgentRun.next() like every other way of driving a run, so pending messages always drain and this error is no longer raised. It is kept so existing except clauses keep working.

AgentRunError

Bases: RuntimeError

Base class for errors occurring during an agent run.

Attributes

message

The error message.

Type: str Default: message

RunCancelled

Bases: AgentRunError

Raised when the agent run was cancelled by the application itself.

Raised by AgentRun.cancel() and RunContext.cancel(), and as its subclass RunTimedOut when a run’s timeout= expires. This is a normal, catchable application-level outcome: the run stopped because your own code asked it to. External cancellation of the task running the agent (asyncio.Task.cancel(), a timeout scope, workflow cancellation under durable execution) is infrastructure-level and keeps propagating as asyncio.CancelledError instead — it is never translated into this exception, and when both race, the external cancellation wins.

Everything the run completed before the cancellation took effect — including the partial response of an interrupted stream and the results of tool calls that finished — is preserved in all_messages(): pass it as message_history to a new run (with a new user prompt or not) to resume the conversation; any tool calls that never produced a result are automatically closed out with synthesized outcome='interrupted' returns before the history is sent to a model.

Cancellation is terminal: capability hooks (wrap_run, wrap_node_run, on_run_error) may observe it and clean up, but cannot recover a cancelled run into a successful result.

Attributes

response

Return the last response from the message history.

Type: ModelResponse

timestamp

Return the timestamp of the last response.

Type: datetime

usage

Return the usage of the cancelled run.

Type: RunUsage

metadata

Metadata associated with this agent run, if configured.

Type: dict[str, Any] | None

run_id

The unique identifier for the agent run, or None if it was cancelled before starting.

Type: str | None

conversation_id

The conversation identifier, or None if the run was cancelled before starting.

Type: str | None

Methods

from_cancellation

@classmethod

def from_cancellation(cls, exc: BaseException) -> RunCancelled | None

Recover run state from a cancellation-related exception.

External cancellation of a plain agent.run() keeps its standard asyncio semantics. Catch it with except asyncio.CancelledError as exc, then call RunCancelled.from_cancellation(exc) to access the partial run state attached by Pydantic AI. This also works with the TimeoutError raised by asyncio.timeout() or asyncio.wait_for(), whose exception chain contains the original CancelledError, and with the KeyboardInterrupt raised by pressing Ctrl-C during agent.run_sync() or agent.run_stream_sync(). An external CancelledError must keep propagating for timeouts and task groups to tear down correctly, so re-raise it after capturing the state rather than returning from the handler; only a first-party RunCancelled is yours to consume.

Passing a RunCancelled directly returns the same instance, providing uniform handling for first-party and external cancellation paths.

This method traverses __context__ to find attached run state. Use capture_run_messages() as the fallback when only message history is needed.

Returns

RunCancelled | None

all_messages
def all_messages() -> list[ModelMessage]

Return the complete resumable history of the cancelled run.

This is a DETACHED snapshot of the run’s message history at termination, ready to pass as message_history for a resumed run.

Returns

list[ModelMessage] — List of messages.

all_messages_json
def all_messages_json() -> bytes

Return all messages from all_messages as JSON bytes.

Returns

bytes — JSON bytes representing the messages.

new_messages
def new_messages() -> list[ModelMessage]

Return the messages produced during the cancelled run.

Messages provided via message_history and messages from older runs are excluded.

Returns

list[ModelMessage] — List of new messages.

new_messages_json
def new_messages_json() -> bytes

Return new messages from new_messages as JSON bytes.

Returns

bytes — JSON bytes representing the new messages.

RunTimedOut

Bases: RunCancelled, TimeoutError

Raised when an agent run doesn’t finish before its deadline.

The deadline comes from timeout= on the agent run methods, or is inherited from the run that started this one from inside a tool (see RunContext.deadline). The run is stopped exactly like RunCancelled, whose subclass this is, so except RunCancelled sees every first-party stop and all_messages() holds everything the run completed, ready to resume from. It is also a TimeoutError, like the error asyncio.timeout() raises.

SuspendedResponseExpired

Bases: AgentRunError

Raised when resuming a suspended response whose server-side job is no longer available.

Suspended/background jobs are only resumable within the provider’s retention window (e.g. ~10 minutes for OpenAI background mode). Resuming a persisted suspended response after that window raises this instead of an opaque provider HTTP error; start a new run from the preceding messages to retry from scratch.

UsageLimitExceeded

Bases: AgentRunError

Error raised when a Model’s usage exceeds the specified limits.

ConcurrencyLimitExceeded

Bases: AgentRunError

Error raised when the concurrency queue depth exceeds max_queued.

UnexpectedModelBehavior

Bases: AgentRunError

Error caused by unexpected Model behavior, e.g. an unexpected response code.

Attributes

message

Description of the unexpected behavior.

Type: str Default: message

body

The body of the response, if available.

Type: str | None Default: json.dumps(json.loads(body), indent=2)

ContentFilterError

Bases: UnexpectedModelBehavior

Raised when content filtering is triggered by the model provider.

ModelAPIError

Bases: AgentRunError

Raised when a model provider API request fails.

Adapters raise one of its category subclasses when the provider’s error says what went wrong: ModelRateLimitError, ModelQuotaExceededError, ModelUnavailableError (and its ModelOverloadedError), ModelServerError, ModelConnectionError (and its ModelTimeoutError), or ModelContextWindowExceededError. When the error came with an HTTP status code, the raised exception is also a ModelHTTPError; see ModelHTTPError.for_category.

A request can be streamed without you asking for it, e.g. when the agent has an event stream handler, so an error the provider sends inside an already open stream is reported the same way as the same error before the stream opened: with the HTTP status the provider uses for it, where that is clear. Such errors have in_stream set.

The provider SDK’s own exception, if any, is available as __cause__.

Attributes

model_name

The name of the model associated with the error.

Type: str Default: model_name

body

The body of the provider’s error response or error event, if available.

Type: object | None Default: body

provider_error_code

The provider’s machine-readable error code, if it sent one.

For example 'rate_limit_exceeded' or 'context_length_exceeded' (OpenAI), 'ThrottlingException' (Bedrock), 'RESOURCE_EXHAUSTED' (Google, xAI), or '3051' (Mistral).

Type: str | None Default: provider_error_code

provider_error_type

The provider’s error type, if it sent one separately from the code.

For example 'overloaded_error' or 'invalid_request_error' (Anthropic, OpenAI).

Type: str | None Default: provider_error_type

retry_after

Seconds the provider asked you to wait before retrying, if it said.

An HTTP error reads it from the retry-after-ms or Retry-After response header.

Type: float | None Default: retry_after

in_stream

Whether the provider reported the error inside a response stream that had already started successfully.

Its status_code, if any, is then the status the provider uses for the same error before a stream opens, rather than the stream’s own, and its headers, if any, are the stream’s.

Type: bool Default: in_stream

ModelRateLimitError

Bases: ModelAPIError

Raised when the provider rejected the request because a rate limit was reached.

For example an HTTP 429 with rate_limit_exceeded, Bedrock’s ThrottlingException, or a gRPC RESOURCE_EXHAUSTED, whether it arrived as an HTTP status or inside a stream. Exhausted quota or billing that the provider says so explicitly is a ModelQuotaExceededError instead, since waiting won’t help.

Check retry_after for how long the provider asked you to wait.

ModelQuotaExceededError

Bases: ModelAPIError

Raised when the provider rejected the request because the account’s quota, credits, or billing is exhausted.

Only raised when the provider says so explicitly, e.g. an HTTP 402, OpenAI’s insufficient_quota, Anthropic’s billing_error, or Bedrock’s ServiceQuotaExceededException. Unlike a ModelRateLimitError, retrying after a wait won’t help.

ModelUnavailableError

Bases: ModelAPIError

Raised when the provider or model was temporarily unable to serve the request.

For example an HTTP 503, Bedrock’s ServiceUnavailableException, or a gRPC UNAVAILABLE sent by the provider, whether it arrived as an HTTP status or inside a stream. When the provider says the cause is load, it’s the more specific ModelOverloadedError.

ModelOverloadedError

Bases: ModelUnavailableError

Raised when the provider or model was temporarily unable to serve the request because it’s overloaded.

Only raised when the provider says so: an HTTP 529, Anthropic’s overloaded_error, Hugging Face Text Generation Inference’s overloaded error, or an unavailable error whose code or message says overloaded. A subclass of ModelUnavailableError.

ModelServerError

Bases: ModelAPIError

Raised when the provider failed with a server error that isn’t otherwise categorized.

For example an HTTP 500, 502 or 504, or a gRPC INTERNAL or DEADLINE_EXCEEDED sent by the provider, whether it arrived as an HTTP status or inside a stream. An unavailable or overloaded provider is a ModelUnavailableError instead.

ModelConnectionError

Bases: ModelAPIError

Raised when the request could not reach the provider or its response could not be read.

For example a refused connection, a reset connection, or a dropped stream. The transport library’s exception is available as __cause__.

Attributes

phase

The stage of the request at which the transport failed, if known.

  • 'pool': waiting for a free connection in the local connection pool. The request was not sent.
  • 'connect': opening the connection to the provider. The request was not sent.
  • 'write': sending the request. It may have been partly or fully sent.
  • 'read': receiving the response, including a stream that broke off. The request was sent, so the provider may have acted on it.

None when the transport error doesn’t say, e.g. a connection closed at an unknown point.

Type: TransportPhase | None Default: phase

ModelTimeoutError

Bases: ModelConnectionError

Raised when a single attempt at the request timed out at the transport layer.

This is the provider SDK’s or HTTP client’s own timeout, controlled by [ModelSettings['timeout']][pydantic_ai.settings.ModelSettings.timeout], and applies to one attempt. A deadline over all attempts at a request is [ModelSettings['request_timeout']][pydantic_ai.settings.ModelSettings.request_timeout], which raises ModelRequestTimeout instead.

ModelContextWindowExceededError

Bases: ModelAPIError

Raised when the provider rejected the request because the input exceeds the model’s context window.

Catch it to compact or truncate the message history and try again; see Compaction. An overflow reported as an HTTP 400 is also a ModelHTTPError with status 400, as before.

FallbackModel falls back on it by default, since a later model may have a larger context window. See Handling context window overflow to change that.

ModelRequestTimeout

Bases: ModelAPIError

Raised when a model request didn’t finish within its [ModelSettings['request_timeout']][pydantic_ai.settings.ModelSettings.request_timeout].

The deadline is enforced by Pydantic AI around one request to one model, so it covers every attempt the provider SDK and HTTP transport make, and reading a streamed response through its last chunk. Under a FallbackModel, each model gets a deadline of its own, and its default fallback_on falls back on this error.

Attributes

timeout

The request_timeout that ran out, in seconds.

Type: float Default: timeout

ModelHTTPError

Bases: ModelAPIError

Raised when a model provider response has a status code of 4xx or 5xx.

An HTTP error that also belongs to an error category is an instance of that category too, e.g. except ModelRateLimitError catches a 429 and except ModelHTTPError still does.

Errors that didn’t come with an HTTP status of their own get the status the provider uses for the same error where that is clear, so they are handled the same way: xAI maps gRPC status codes (e.g. RESOURCE_EXHAUSTED to 429), OpenRouter uses the code of an error inside a 200 response, and an error inside an open stream gets the status of the same error before the stream opened, with in_stream set.

Attributes

status_code

The HTTP status code returned by the API.

Type: int Default: status_code

headers

Response headers from the provider, with keys lowercased for consistent access.

For example, use exc.headers.get('retry-after') to read the Retry-After header regardless of provider casing. None when the provider does not supply headers (e.g. gRPC-based providers or synthesised errors).

Type: dict[str, str] | None Default: {(k.lower()): v for k, v in (headers.items())} if headers is not None else None

suggested_model_id

A close known model identifier suggested from a provider-confirmed model-name error.

Type: str | None Default: suggested_model_id

hint

Guidance on resolving the error, appended to the exception message.

For example, the account setting a provider requires.

Type: str | None Default: hint

provider_retry_hint

Whether the provider said retrying the request may succeed, from its x-should-retry response header.

None when the header is absent or isn’t true or false. OpenAI and Anthropic send it, and their SDKs follow it when they retry.

Type: bool | None

Methods

for_category

@staticmethod

def for_category(
    category: type[ModelRateLimitError | ModelQuotaExceededError | ModelUnavailableError | ModelServerError | ModelContextWindowExceededError] | None,
    *,
    status_code: int,
    model_name: str,
    body: object | None = None,
    headers: Mapping[str, str] | None = None,
    suggested_model_id: str | None = None,
    hint: str | None = None,
    provider_error_code: str | None = None,
    provider_error_type: str | None = None,
    retry_after: float | None = None,
    in_stream: bool = False,
) -> ModelHTTPError

Create a ModelHTTPError that is also an instance of the error category, as Pydantic AI’s models raise.

Use it in a custom model or a test to raise an HTTP error that both except ModelHTTPError and except the category catch:

for_category.py
from pydantic_ai import ModelHTTPError, ModelRateLimitError

error = ModelHTTPError.for_category(ModelRateLimitError, status_code=429, model_name='my-model')
print(isinstance(error, ModelHTTPError), isinstance(error, ModelRateLimitError))
#> True True
Returns

ModelHTTPError

Parameters

The error category, or None for a plain ModelHTTPError. One of ModelRateLimitError, ModelQuotaExceededError, ModelUnavailableError, ModelOverloadedError, ModelServerError, or ModelContextWindowExceededError.

status_code : int

The HTTP status code.

model_name : str

The name of the model.

body : object | None Default: None

The body of the error response.

headers : Mapping[str, str] | None Default: None

The response headers.

suggested_model_id : str | None Default: None

A close known model identifier, for a model-name error.

hint : str | None Default: None

Guidance on resolving the error, appended to the message.

provider_error_code : str | None Default: None

The provider’s machine-readable error code.

provider_error_type : str | None Default: None

The provider’s error type.

retry_after : float | None Default: None

Seconds the provider asked to wait; read from headers when not given.

in_stream : bool Default: False

Whether the provider reported the error inside an already open stream.

FallbackExceptionGroup

Bases: ExceptionGroup[Any]

A group of exceptions that can be raised when all fallback models fail.

Attributes

attempts

Every attempt the FallbackModel made, in order.

Unlike the grouped exceptions, this includes the usage of any response that was rejected by a fallback_on response handler, which the agent also adds to the run’s RunUsage. Only set on the group a FallbackModel raised itself: it doesn’t survive a durable execution boundary, such as a Temporal activity.

Type: Sequence[ModelRequestAttempt] Default: ()

ToolRetryError

Bases: Exception

Exception used to signal a retry message should be returned to the LLM.

tool_retry is whichever part the retry travels as: a ToolReturnPart with outcome='retried' when it answers a tool call, a RetryFeedbackPart when it doesn’t. A deprecated RetryPromptPart passed in is translated into the one it always meant.

ToolFailedError

Bases: Exception

Exception used to signal a failed ToolReturnPart should be returned to the LLM.

IncompleteToolCall

Bases: UnexpectedModelBehavior

Error raised when a model stops due to token limit while emitting a tool call.

MessageHistoryMutatedWarning

Bases: Warning

Warning raised when in-place mutation of the message history is detected at the end of a run.

Mutating messages that are already part of the run’s history in place (e.g. ctx.messages[0].parts[0].content = '...' from a tool) is not supported: the per-request gen_ai.input.messages span attribute caches each message’s serialized form, so spans recorded after the mutation may not match the messages actually sent to the model. The run-level pydantic_ai.all_messages attribute is always serialized fresh and does reflect the mutation. To transform history mid-run, build new message or part objects instead — e.g. with dataclasses.replace, passing the message a new parts list (replacing a message in the history and reassigning its parts list are both safe) — for instance in a history processor (ProcessHistory).

The warning is best-effort: it’s raised when a mutation is detected at the end of a successful run, which covers messages still present in the final history. Errored runs aren’t checked — with warnings configured as errors, the warning would displace the run’s own exception. Its absence does not guarantee that no stale span was recorded.

UnsupportedSettingWarning

Bases: UserWarning

Warning emitted when a model ignores a ModelSettings field that a request relies on.

Most settings a model doesn’t support, like temperature or seed, are tuning knobs that are silently ignored, so the same settings work across models. This warning covers the ones whose absence changes what the request guarantees: timeout, max_retries, stop_sequences, parallel_tool_calls=False (when the request has function tools), extra_headers and extra_body. Each field’s Supported by: list names the models that honor it.

It’s emitted wherever the setting comes from: the run, the agent, a capability or the model’s own settings. The stop_sequences of an MCP server’s sampling request don’t warn, since the server chose them, not you. To turn it into an error, use a warnings filter:

import warnings

from pydantic_ai import UnsupportedSettingWarning

warnings.filterwarnings('error', category=UnsupportedSettingWarning)

TransportPhase

The stage of a request at which a transport failure happened; see ModelConnectionError.phase.

Default: Literal['pool', 'connect', 'write', 'read']