Skip to main content

Configuring Error Reporting and Privacy

You can customize how validation errors are reported and protect sensitive data by configuring CoreConfig when initializing a SchemaValidator. This allows you to redact input values from error messages and preserve the original Python exceptions that caused a validation failure.

Hiding Sensitive Input Data

To prevent sensitive information (like passwords or PII) from appearing in logs or error representations, set hide_input_in_errors to True in your CoreConfig.

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

# Define a schema that hides input data in errors
config = CoreConfig(hide_input_in_errors=True)
validator = SchemaValidator(
cs.model_schema(
cls=dict,
schema=cs.model_fields_schema(
fields={'password': cs.model_field(schema=cs.str_schema())}
)
),
config=config,
)

try:
# Attempt to validate an invalid type (int instead of str)
validator.validate_python({'password': 12345})
except ValidationError as exc:
# The error message will NOT contain 'input_value=12345'
assert 'input_value=12345' not in str(exc)
assert 'type=string_type' in str(exc)

# Structured errors also omit the 'input' key
for error in exc.errors():
assert 'input' not in error

When hide_input_in_errors is False (the default), the error representation includes the input value and type: Input should be a valid string [type=string_type, input_value=12345, input_type=int]

When enabled, it is reduced to: Input should be a valid string [type=string_type]

Preserving Original Exception Causes

When using custom validator functions, you can attach the original Python exception to the ValidationError by setting validation_error_cause to True. This is useful for debugging complex validation logic.

from pydantic_core import SchemaValidator, core_schema, CoreConfig, ValidationError

def custom_validator(v):
if v == "fail":
# This original exception will be preserved
raise ValueError("Internal validation logic failed")
return v

config = CoreConfig(validation_error_cause=True)
validator = SchemaValidator(
core_schema.no_info_plain_validator_function(custom_validator),
config=config
)

try:
validator.validate_python("fail")
except ValidationError as exc:
# The original ValueError is wrapped in an ExceptionGroup and attached to __cause__
cause_group = exc.__cause__
assert len(cause_group.exceptions) == 1
assert isinstance(cause_group.exceptions[0], ValueError)
assert str(cause_group.exceptions[0]) == "Internal validation logic failed"

Requirements for Exception 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 an exception occurs.

By default, pydantic-core includes a URL to the Pydantic documentation in the ValidationError string representation. You can control this globally using environment variables.

  • Disable URLs: Set PYDANTIC_ERRORS_INCLUDE_URL=0 or PYDANTIC_ERRORS_INCLUDE_URL=false.
  • Enable URLs: Set PYDANTIC_ERRORS_INCLUDE_URL=1 (default).

[!IMPORTANT] Environment variables for error reporting must be set before ValidationError.__repr__ is called for the first time in your process to take effect.

Troubleshooting

Missing Input in Manual Errors

If you are manually raising a ValidationError using from_exception_data, you must pass the hide_input argument to match your schema's privacy settings:

from pydantic_core import ValidationError

# Manually redact input in a custom error
exc = ValidationError.from_exception_data(
'MyModel',
[{'type': 'greater_than', 'loc': ('val',), 'input': 4, 'ctx': {'gt': 5}}],
hide_input=True
)
assert 'input_value=4' not in str(exc)

Traceback Loss

If you find that tracebacks are missing when using validation_error_cause, ensure you are not catching and re-raising exceptions without the from keyword inside your custom validators. pydantic-core preserves the __cause__ chain of the exceptions it captures.