Skip to main content

Configuring Error Reporting

The CoreConfig class in pydantic_core.core_schema provides several options to customize how validation errors are reported. These settings allow developers to control the visibility of sensitive data, improve the traceability of errors back to the input source, and preserve the context of exceptions raised within custom validators.

Hiding Input Data

By default, ValidationError representations include the input value that failed validation. In production environments, this can lead to sensitive data (like passwords or PII) being logged. The hide_input_in_errors setting allows you to suppress this information.

When hide_input_in_errors is set to True, the input_value and input_type are omitted from the error's string representation.

from pydantic_core import CoreConfig, SchemaValidator, ValidationError
from pydantic_core import core_schema as cs

# Configuration to hide input data
config = CoreConfig(hide_input_in_errors=True)

v = SchemaValidator(
cs.model_schema(
cls=dict,
schema=cs.model_fields_schema(
fields={'password': cs.model_field(schema=cs.str_schema())}
)
),
config=config,
)

try:
# Providing an integer instead of a string
v.validate_python({'password': 12345})
except ValidationError as e:
# The error message will NOT contain "input_value=12345"
# It will look like: "Input should be a valid string [type=string_type]"
print(e)

Mapping Errors to Input Structure

When working with aliases, the error location (loc) can either point to the internal field name or the path used in the input data. The loc_by_alias setting (which defaults to True) determines this behavior.

Using loc_by_alias=True is particularly useful for complex input structures where a single field might be populated from multiple possible alias paths. It ensures the error message points exactly where the problem occurred in the provided data.

# Example from pydantic-core/tests/validators/test_model_fields.py
v = SchemaValidator(
cs.model_fields_schema(
fields={
'field_a': cs.model_field(
validation_alias=['foo', 'x'],
schema=cs.int_schema()
)
}
),
config=CoreConfig(loc_by_alias=True),
)

try:
v.validate_python({'foo': {'x': 'not_int'}})
except ValidationError as e:
# loc will be ('foo', 'x') because loc_by_alias is True
assert e.errors()[0]['loc'] == ('foo', 'x')

# If loc_by_alias were False:
v_no_alias = SchemaValidator(
cs.model_fields_schema(
fields={
'field_a': cs.model_field(
validation_alias=['foo', 'x'],
schema=cs.int_schema()
)
}
),
config=CoreConfig(loc_by_alias=False),
)

try:
v_no_alias.validate_python({'foo': {'x': 'not_int'}})
except ValidationError as e:
# loc will be ('field_a',) regardless of the input path
assert e.errors()[0]['loc'] == ('field_a',)

Preserving Exception Context

When a custom validator (e.g., a function validator) raises a Python exception, pydantic-core catches it and wraps it in a ValidationError. By default, the original exception is not attached to the ValidationError's __cause__.

Setting validation_error_cause=True enables the attachment of these exceptions. This is invaluable for debugging complex validation logic.

Exception Groups and Python Versions

This feature utilizes ExceptionGroup (or BaseExceptionGroup) to store the underlying causes.

  • Python 3.11+: Uses the built-in ExceptionGroup.
  • Python < 3.11: Requires the exceptiongroup backport package. If the package is missing and validation_error_cause is enabled, an ImportError will be raised during validation if a user exception occurs.
# Example based on pydantic-core/tests/test_errors.py
def custom_validator(v):
if v == 'fail':
raise ValueError('Internal logic failed')
return v

v = SchemaValidator(
cs.no_info_plain_validator_function(custom_validator),
config=CoreConfig(validation_error_cause=True)
)

try:
v.validate_python('fail')
except ValidationError as e:
# e.__cause__ is an ExceptionGroup containing the ValueError
cause_group = e.__cause__
original_exc = cause_group.exceptions[0]
print(f'Caught original exception: {original_exc}')

When enabled, pydantic-core also appends a note to the original exception (using __notes__ in Python 3.11+) to indicate it was captured during Pydantic validation, preserving the full traceback of the original failure.