Skip to main content

Customizing Error Responses in Schemas

To customize validation error responses in this codebase, you can use core_schema.custom_error_schema to wrap existing schemas and override their default error types, messages, and context. This is useful for providing domain-specific error identifiers and human-readable messages.

Overriding Errors in a Schema

The most direct way to customize an error is to wrap a CoreSchema with custom_error_schema. This ensures that any validation failure within the wrapped schema returns your specified error details.

from pydantic_core import SchemaValidator, core_schema

# Wrap an integer schema with a custom error
schema = core_schema.custom_error_schema(
core_schema.int_schema(),
custom_error_type='my_custom_error',
custom_error_message='The provided value must be a valid integer'
)

v = SchemaValidator(schema)

try:
v.validate_python('not-an-int')
except Exception as exc:
# The error now uses the custom type and message
print(exc.errors())
# Output: [{'type': 'my_custom_error', 'loc': (), 'msg': 'The provided value must be a valid integer', 'input': 'not-an-int'}]

Key Configuration Fields

When using CustomErrorSchema (via the core_schema.custom_error_schema helper), you can configure the following:

  • custom_error_type: A string identifier (slug) for the error. This is used programmatically to identify the error type.
  • custom_error_message: A human-readable string. If not provided, and the type matches a known Pydantic error, the default message for that type is used.
  • custom_error_context: A dictionary of values (strings, ints, or floats) that can be used to provide additional metadata about the error.

Manual Error Generation

If you need to generate validation errors programmatically (for example, in a custom validator or when re-raising errors), use InitErrorDetails with ValidationError.from_exception_data.

from pydantic_core import ValidationError, InitErrorDetails

errors = [
InitErrorDetails(
type='value_error',
loc=('field_name',),
input='invalid_input',
ctx={'reason': 'Value is too long'}
)
]

# Manually create a ValidationError
raise ValidationError.from_exception_data('MyModel', errors)

Using Known Error Types

You can use custom_error_schema to trigger standard Pydantic errors even if the underlying schema doesn't naturally produce them. However, there is a restriction: if the custom_error_type matches a built-in error type (like recursion_loop), you cannot provide a custom_error_message.

from pydantic_core import SchemaValidator, core_schema

# This is valid: it uses the default message for 'recursion_loop'
schema = core_schema.custom_error_schema(
core_schema.int_schema(),
'recursion_loop'
)

v = SchemaValidator(schema)
# Validation failure will result in:
# {'type': 'recursion_loop', 'msg': 'Recursion error - cyclic reference detected', ...}

Troubleshooting

SchemaError: custom_error_message should not be provided

If you attempt to provide a custom_error_message while using a custom_error_type that matches a known Pydantic error, a SchemaError will be raised during validator initialization.

from pydantic_core import SchemaValidator, core_schema, SchemaError
import pytest

# This will raise a SchemaError
with pytest.raises(SchemaError, match="custom_error_message should not be provided"):
SchemaValidator(
core_schema.custom_error_schema(
core_schema.int_schema(),
'recursion_loop',
custom_error_message='Custom message'
)
)

Accessing Processed Error Details

When a ValidationError is caught, you can retrieve the structured ErrorDetails by calling .errors(). This converts the internal error representation into a list of dictionaries containing the type, loc, msg, input, and optional ctx and url.

try:
v.validate_python(input_data)
except ValidationError as exc:
error_list = exc.errors(include_url=False, include_context=True)
for error in error_list:
print(f"Error Type: {error['type']}, Message: {error['msg']}")