Skip to content

pydantic_ai.exceptions

ModelRetry

Bases: Exception

Exception to raise when a tool function should be retried.

The agent will return the message to the model and ask it to try calling the function/tool again.

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class ModelRetry(Exception):
    """Exception to raise when a tool function should be retried.

    The agent will return the message to the model and ask it to try calling the function/tool again.
    """

    message: str
    """The message to return to the model."""

    def __init__(self, message: str):
        self.message = message
        super().__init__(message)

    def __eq__(self, other: Any) -> bool:
        return isinstance(other, self.__class__) and other.message == self.message

    def __hash__(self) -> int:
        return hash((self.__class__, self.message))

    @classmethod
    def __get_pydantic_core_schema__(cls, _: Any, __: Any) -> core_schema.CoreSchema:
        """Pydantic core schema to allow `ModelRetry` to be (de)serialized."""
        schema = core_schema.typed_dict_schema(
            {
                'message': core_schema.typed_dict_field(core_schema.str_schema()),
                'kind': core_schema.typed_dict_field(core_schema.literal_schema(['model-retry'])),
            }
        )
        return core_schema.no_info_after_validator_function(
            lambda dct: ModelRetry(dct['message']),
            schema,
            serialization=core_schema.plain_serializer_function_ser_schema(
                lambda x: {'message': x.message, 'kind': 'model-retry'},
                return_schema=schema,
            ),
        )

message instance-attribute

message: str = message

The message to return to the model.

__get_pydantic_core_schema__ classmethod

__get_pydantic_core_schema__(_: Any, __: Any) -> CoreSchema

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

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
@classmethod
def __get_pydantic_core_schema__(cls, _: Any, __: Any) -> core_schema.CoreSchema:
    """Pydantic core schema to allow `ModelRetry` to be (de)serialized."""
    schema = core_schema.typed_dict_schema(
        {
            'message': core_schema.typed_dict_field(core_schema.str_schema()),
            'kind': core_schema.typed_dict_field(core_schema.literal_schema(['model-retry'])),
        }
    )
    return core_schema.no_info_after_validator_function(
        lambda dct: ModelRetry(dct['message']),
        schema,
        serialization=core_schema.plain_serializer_function_ser_schema(
            lambda x: {'message': x.message, 'kind': 'model-retry'},
            return_schema=schema,
        ),
    )

CallDeferred

Bases: Exception

Exception to raise when a tool call should be deferred.

See tools docs for more information.

Parameters:

Name Type Description Default
metadata dict[str, Any] | 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.

None
Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
class CallDeferred(Exception):
    """Exception to raise when a tool call should be deferred.

    See [tools docs](../deferred-tools.md#deferred-tools) for more information.

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

    def __init__(self, metadata: dict[str, Any] | None = None):
        self.metadata = metadata
        super().__init__()

    def __reduce__(self) -> tuple[type, tuple[Any, ...]]:
        return self.__class__, (self.metadata,)

ApprovalRequired

Bases: Exception

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

See tools docs for more information.

Parameters:

Name Type Description Default
metadata dict[str, Any] | 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.

None
Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
class ApprovalRequired(Exception):
    """Exception to raise when a tool call requires human-in-the-loop approval.

    See [tools docs](../deferred-tools.md#human-in-the-loop-tool-approval) for more information.

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

    def __init__(self, metadata: dict[str, Any] | None = None):
        self.metadata = metadata
        super().__init__()

    def __reduce__(self) -> tuple[type, tuple[Any, ...]]:
        return self.__class__, (self.metadata,)

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.

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
113
114
115
116
117
118
119
120
121
122
123
class SkipModelRequest(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.
    """

    response: ModelResponse

    def __init__(self, response: ModelResponse):
        self.response = response
        super().__init__()

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.

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
126
127
128
129
130
131
132
133
134
135
136
class SkipToolValidation(Exception):
    """Exception to raise in before/wrap tool validate hooks to skip validation.

    The provided args will be used as the validated arguments.
    """

    validated_args: dict[str, Any]

    def __init__(self, validated_args: dict[str, Any]):
        self.validated_args = validated_args
        super().__init__()

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.

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
139
140
141
142
143
144
145
146
147
148
149
class SkipToolExecution(Exception):
    """Exception to raise in before/wrap tool execute hooks to skip execution.

    The provided result will be used as the tool result.
    """

    result: Any

    def __init__(self, result: Any):
        self.result = result
        super().__init__()

UserError

Bases: RuntimeError

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

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
152
153
154
155
156
157
158
159
160
class UserError(RuntimeError):
    """Error caused by a usage mistake by the application developer — You!"""

    message: str
    """Description of the mistake."""

    def __init__(self, message: str):
        self.message = message
        super().__init__(message)

message instance-attribute

message: str = message

Description of the mistake.

AgentRunError

Bases: RuntimeError

Base class for errors occurring during an agent run.

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
163
164
165
166
167
168
169
170
171
172
173
174
class AgentRunError(RuntimeError):
    """Base class for errors occurring during an agent run."""

    message: str
    """The error message."""

    def __init__(self, message: str):
        self.message = message
        super().__init__(message)

    def __str__(self) -> str:
        return self.message

message instance-attribute

message: str = message

The error message.

UsageLimitExceeded

Bases: AgentRunError

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

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
177
178
class UsageLimitExceeded(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.

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
181
182
class ConcurrencyLimitExceeded(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.

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
class UnexpectedModelBehavior(AgentRunError):
    """Error caused by unexpected Model behavior, e.g. an unexpected response code."""

    message: str
    """Description of the unexpected behavior."""
    body: str | None
    """The body of the response, if available."""

    def __init__(self, message: str, body: str | None = None):
        self.message = message
        if body is None:
            self.body: str | None = None
        else:
            try:
                self.body = json.dumps(json.loads(body), indent=2)
            except ValueError:
                self.body = body
        super().__init__(message)

    def __reduce__(self) -> tuple[type, tuple[Any, ...]]:
        return self.__class__, (self.message, self.body)

    def __str__(self) -> str:
        if self.body:
            return f'{self.message}, body:\n{self.body}'
        else:
            return self.message

message instance-attribute

message: str = message

Description of the unexpected behavior.

body instance-attribute

body: str | None = dumps(loads(body), indent=2)

The body of the response, if available.

ContentFilterError

Bases: UnexpectedModelBehavior

Raised when content filtering is triggered by the model provider resulting in an empty response.

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
214
215
class ContentFilterError(UnexpectedModelBehavior):
    """Raised when content filtering is triggered by the model provider resulting in an empty response."""

ModelAPIError

Bases: AgentRunError

Raised when a model provider API request fails.

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
218
219
220
221
222
223
224
225
226
227
228
229
class ModelAPIError(AgentRunError):
    """Raised when a model provider API request fails."""

    model_name: str
    """The name of the model associated with the error."""

    def __init__(self, model_name: str, message: str):
        self.model_name = model_name
        super().__init__(message)

    def __reduce__(self) -> tuple[type, tuple[Any, ...]]:
        return self.__class__, (self.model_name, self.message)

model_name instance-attribute

model_name: str = model_name

The name of the model associated with the error.

ModelHTTPError

Bases: ModelAPIError

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

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
class ModelHTTPError(ModelAPIError):
    """Raised when an model provider response has a status code of 4xx or 5xx."""

    status_code: int
    """The HTTP status code returned by the API."""

    body: object | None
    """The body of the response, if available."""

    def __init__(self, status_code: int, model_name: str, body: object | None = None):
        self.status_code = status_code
        self.body = body
        message = f'status_code: {status_code}, model_name: {model_name}, body: {body}'
        super().__init__(model_name=model_name, message=message)

    def __reduce__(self) -> tuple[type, tuple[Any, ...]]:
        return self.__class__, (self.status_code, self.model_name, self.body)

status_code instance-attribute

status_code: int = status_code

The HTTP status code returned by the API.

body instance-attribute

body: object | None = body

The body of the response, if available.

FallbackExceptionGroup

Bases: ExceptionGroup[Any]

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

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
251
252
class FallbackExceptionGroup(ExceptionGroup[Any]):
    """A group of exceptions that can be raised when all fallback models fail."""

ToolRetryError

Bases: Exception

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

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
class ToolRetryError(Exception):
    """Exception used to signal a `ToolRetry` message should be returned to the LLM."""

    def __init__(self, tool_retry: RetryPromptPart):
        self.tool_retry = tool_retry
        message = (
            tool_retry.content
            if isinstance(tool_retry.content, str)
            else self._format_error_details(tool_retry.content, tool_retry.tool_name)
        )
        super().__init__(message)

    def __reduce__(self) -> tuple[type, tuple[Any, ...]]:
        return self.__class__, (self.tool_retry,)

    @staticmethod
    def _format_error_details(errors: list[pydantic_core.ErrorDetails], tool_name: str | None) -> str:
        """Format ErrorDetails as a human-readable message.

        We format manually rather than using ValidationError.from_exception_data because
        some error types (value_error, assertion_error, etc.) require an 'error' key in ctx,
        but when ErrorDetails are serialized, exception objects are stripped from ctx.
        The 'msg' field already contains the human-readable message, so we use that directly.
        """
        error_count = len(errors)
        lines = [
            f'{error_count} validation error{"" if error_count == 1 else "s"}{f" for {tool_name!r}" if tool_name else ""}'
        ]
        for e in errors:
            loc = '.'.join(str(x) for x in e['loc']) if e['loc'] else '__root__'
            lines.append(loc)
            lines.append(f'  {e["msg"]} [type={e["type"]}, input_value={e["input"]!r}]')
        return '\n'.join(lines)

IncompleteToolCall

Bases: UnexpectedModelBehavior

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

Source code in pydantic_ai_slim/pydantic_ai/exceptions.py
290
291
class IncompleteToolCall(UnexpectedModelBehavior):
    """Error raised when a model stops due to token limit while emitting a tool call."""