Skip to main content

How to Raise Custom Errors

To manually trigger validation failures within custom validators, use PydanticCustomError for new error types or PydanticKnownError to reuse Pydantic's built-in error logic.

Raise a New Error Type with PydanticCustomError

Use PydanticCustomError when you need a specific error type and a custom message template. The message can include placeholders that are dynamically filled using a context dictionary.

from pydantic_core import PydanticCustomError, core_schema, SchemaValidator

def validate_even(input_value: int, info: core_schema.ValidationInfo) -> int:
if input_value % 2 != 0:
# 'not_even' is the error type slug
# {val} is a placeholder for the context value
raise PydanticCustomError(
'not_even',
'The value {val} is not even',
{'val': input_value}
)
return input_value

schema = core_schema.with_info_plain_validator_function(validate_even)
v = SchemaValidator(schema)

try:
v.validate_python(3)
except Exception as exc:
print(exc.errors())
# Output: [{'type': 'not_even', 'loc': (), 'msg': 'The value 3 is not even', 'input': 3, 'ctx': {'val': 3}}]

This pattern is used extensively in pydantic/types.py for specialized types like byte sizes:

# From pydantic/types.py
raise PydanticCustomError('byte_size_unit', 'could not interpret byte unit: {unit}', {'unit': unit})

Reuse Built-in Errors with PydanticKnownError

Use PydanticKnownError to trigger one of Pydantic's standard validation errors (e.g., greater_than, too_short, int_type). This ensures your custom validator remains consistent with Pydantic's internal error reporting and localization.

from pydantic_core import PydanticKnownError, core_schema, SchemaValidator

def validate_threshold(input_value: int, info: core_schema.ValidationInfo) -> int:
threshold = 42
if input_value <= threshold:
# Reuses the 'greater_than' error type and its standard message
raise PydanticKnownError('greater_than', {'gt': threshold})
return input_value

schema = core_schema.with_info_plain_validator_function(validate_threshold)
v = SchemaValidator(schema)

try:
v.validate_python(10)
except Exception as exc:
print(exc.errors())
# Output: [{'type': 'greater_than', 'loc': (), 'msg': 'Input should be greater than 42', 'input': 10, 'ctx': {'gt': 42}}]

Standard validators in pydantic/_internal/_validators.py use this to enforce constraints:

# From pydantic/_internal/_validators.py
if not (x > gt):
raise PydanticKnownError('greater_than', {'gt': _safe_repr(gt)})

Declarative Error Overrides with custom_error_schema

If you want a specific schema branch to always return a custom error upon failure without writing a full validator function, use core_schema.custom_error_schema. This wraps an existing schema and replaces any error it produces with your custom one.

from pydantic_core import core_schema, SchemaValidator

schema = core_schema.custom_error_schema(
core_schema.int_schema(),
custom_error_type='integer_required',
custom_error_message='Please provide a valid integer, you provided {input}',
custom_error_context={'input': 'invalid data'}
)

v = SchemaValidator(schema)
# Any non-integer input will now trigger 'integer_required' instead of 'int_type'

Usage in Different Validator Types

You can raise these errors in any validator function supported by pydantic-core.

Before Validator

Used to validate or transform raw input before it reaches the inner schema.

# From pydantic-core/tests/test_errors.py
def validator(input_value, info):
raise PydanticCustomError('my_error', 'my message with {val}', {'val': 42})

schema = core_schema.with_info_before_validator_function(
validator,
core_schema.int_schema()
)

Wrap Validator

Used when you need to control whether the inner validation runs at all, or if you want to catch its errors and re-raise them as custom ones.

# From pydantic/_internal/_validators.py
def sequence_validator(input_value, validator):
if isinstance(input_value, (str, bytes)):
raise PydanticCustomError(
'sequence_str',
"'{type_name}' instances are not allowed as a Sequence value",
{'type_name': type(input_value).__name__},
)
return validator(input_value)

Troubleshooting

  • Context Key Mismatch: If you use a placeholder like {val} in your message template but do not provide val in the context dictionary, the message will remain unformatted (e.g., "The value {val} is not even").
  • Invalid Known Error Slug: PydanticKnownError requires a valid error type slug. Providing an unknown slug will result in a KeyError at runtime when the error is generated.
  • Catching Errors: These errors must be raised inside a validator function managed by a SchemaValidator. If raised outside, they behave like standard Python exceptions and will not be collected into a ValidationError.
  • Subclassing: You can subclass PydanticCustomError to create domain-specific exceptions that still integrate with Pydantic's validation system.