CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pydantic-core

Core functionality for Pydantic validation and serialization

Pending
Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Comprehensive error handling system with detailed error information, location tracking, and support for custom error messages and error type definitions. Pydantic Core provides rich error reporting that helps developers understand validation failures.

Capabilities

Main Exception Classes

Core exception classes for different types of validation and serialization errors.

class ValidationError(ValueError):
    """
    Main validation error with detailed error information.
    
    Raised when data validation fails, containing detailed information
    about what went wrong, where it went wrong, and the context.
    """
    
    def errors(self) -> list[ErrorDetails]:
        """
        Get detailed information about all validation errors.
        
        Returns:
            List of error details with location, message, and context
        """
    
    def error_count(self) -> int:
        """
        Get the total number of validation errors.
        
        Returns:
            Number of errors
        """
    
    def __str__(self) -> str:
        """
        Get a human-readable error message.
        
        Returns:
            Formatted error message
        """

class PydanticCustomError(ValueError):
    """
    Custom validation error with user-defined messages.
    
    Allows developers to create validation errors with custom
    error types and message templates.
    """
    
    def __init__(self, error_type: str, message_template: str, context: dict = None):
        """
        Create a custom validation error.
        
        Args:
            error_type: String identifier for the error type
            message_template: Template string for the error message
            context: Context values for message template formatting
        """

class PydanticKnownError(ValueError):
    """
    Pre-defined validation error for known error types.
    
    Used for standard validation errors with pre-defined
    error types and message templates.
    """
    
    def __init__(self, error_type: ErrorType, context: dict = None):
        """
        Create a known validation error.
        
        Args:
            error_type: Pre-defined error type
            context: Context values for message formatting
        """

class SchemaError(Exception):
    """
    Schema definition and building errors.
    
    Raised when there are problems with schema definitions,
    such as invalid schema structures or conflicting constraints.
    """

class PydanticSerializationError(ValueError):
    """
    Serialization process errors.
    
    Raised when data cannot be serialized due to unsupported
    types or serialization constraints.
    """

class PydanticSerializationUnexpectedValue(PydanticSerializationError):
    """
    Unexpected value during serialization.
    
    Raised when the serializer encounters a value that doesn't
    match the expected schema during serialization.
    """

Error Information Structures

TypedDict structures that provide detailed error information.

ErrorDetails = TypedDict('ErrorDetails', {
    'type': str,  # Error type identifier
    'loc': tuple[int | str, ...],  # Location tuple (field path)
    'msg': str,  # Human-readable error message
    'input': Any,  # The input value that caused the error
    'ctx': NotRequired[dict[str, Any]],  # Additional error context
    'url': NotRequired[str]  # Documentation URL for the error
})

InitErrorDetails = TypedDict('InitErrorDetails', {
    'type': Union[str, PydanticCustomError],  # Error type or custom error
    'loc': NotRequired[tuple[int | str, ...]],  # Location tuple
    'input': Any,  # The input value that caused the error
    'ctx': NotRequired[dict[str, Any]]  # Additional error context
})

ErrorTypeInfo = TypedDict('ErrorTypeInfo', {
    'type': ErrorType,  # The error type
    'message_template_python': str,  # Message template for Python input
    'example_message_python': str,  # Example message for Python input
    'message_template_json': NotRequired[str],  # Message template for JSON input
    'example_message_json': NotRequired[str],  # Example message for JSON input
    'example_context': dict[str, Any] | None  # Example context values
})

Error Type Constants

Pre-defined error types for common validation failures.

ErrorType = Literal[
    # General validation errors
    'missing', 'extra_forbidden', 'value_error', 'assertion_error', 'type_error',
    
    # Boolean validation errors
    'bool_parsing', 'bool_type',
    
    # Integer validation errors
    'int_parsing', 'int_type', 'int_parsing_size', 'int_from_float',
    'int_greater_than', 'int_greater_than_equal', 'int_less_than', 
    'int_less_than_equal', 'int_multiple_of',
    
    # Float validation errors
    'float_parsing', 'float_type', 'float_finite_number',
    'float_greater_than', 'float_greater_than_equal', 'float_less_than',
    'float_less_than_equal', 'float_multiple_of',
    
    # String validation errors
    'string_type', 'string_too_short', 'string_too_long', 'string_pattern_mismatch',
    'string_unicode', 'string_sub_type',
    
    # Bytes validation errors
    'bytes_type', 'bytes_too_short', 'bytes_too_long',
    
    # Date and time validation errors
    'date_parsing', 'date_type', 'date_future', 'date_past',
    'time_parsing', 'time_type',
    'datetime_parsing', 'datetime_type', 'datetime_future', 'datetime_past',
    'datetime_aware', 'datetime_naive',
    'timedelta_parsing', 'timedelta_type',
    'timezone_naive', 'timezone_aware',
    
    # Collection validation errors
    'list_type', 'tuple_type', 'set_type', 'frozenset_type', 'dict_type',
    'too_short', 'too_long',
    
    # Advanced type validation errors
    'is_instance_of', 'is_subclass_of', 'callable_type',
    'literal_error', 'enum_parsing',
    'union_tag_invalid', 'union_tag_not_found',
    
    # URL validation errors
    'url_parsing', 'url_syntax_violation', 'url_too_long', 'url_scheme',
    
    # UUID validation errors
    'uuid_parsing', 'uuid_version',
    
    # Decimal validation errors
    'decimal_parsing', 'decimal_type', 'decimal_max_digits',
    'decimal_max_places', 'decimal_whole_digits',
    
    # JSON validation errors
    'json_invalid', 'json_type',
    
    # Model validation errors
    'model_type', 'model_attributes_type', 'model_class',
    'dataclass_type', 'dataclass_exact_type',
    
    # Custom and function validation errors
    'custom_error', 'validator_error', 'function_no_validator',
    'function_after_field_validator', 'function_before_field_validator',
    'function_wrap_validator', 'function_plain_validator',
    
    # And many more...
]

Utility Functions

Functions for working with error information.

def list_all_errors() -> list[ErrorTypeInfo]:
    """
    Get information about all possible validation error types.
    
    Returns:
        List of error type information including message templates and examples
    """

Usage Examples

Basic Error Handling

from pydantic_core import SchemaValidator, ValidationError
from pydantic_core.core_schema import dict_schema, str_schema, int_schema

# Create a schema
schema = dict_schema({
    'name': str_schema(min_length=2),
    'age': int_schema(ge=0, le=120),
    'email': str_schema()
})

validator = SchemaValidator(schema)

# Try to validate invalid data
try:
    invalid_data = {
        'name': 'A',  # Too short
        'age': 150,   # Too high
        'email': ''   # Empty string
    }
    validator.validate_python(invalid_data)
except ValidationError as e:
    print(f"Validation failed with {e.error_count()} errors:")
    
    for error in e.errors():
        location = ' -> '.join(map(str, error['loc']))
        print(f"  {location}: {error['msg']}")
        print(f"    Input: {error['input']}")
        print(f"    Type: {error['type']}")
        if 'ctx' in error:
            print(f"    Context: {error['ctx']}")
        print()

# Output:
# Validation failed with 3 errors:
#   name: String should have at least 2 characters
#     Input: A
#     Type: string_too_short
#     Context: {'min_length': 2}
#
#   age: Input should be less than or equal to 120
#     Input: 150
#     Type: int_less_than_equal
#     Context: {'le': 120}
#
#   email: String should have at least 1 character
#     Input: 
#     Type: string_too_short
#     Context: {'min_length': 1}

Nested Data Error Locations

from pydantic_core import SchemaValidator, ValidationError
from pydantic_core.core_schema import dict_schema, list_schema, str_schema, int_schema

# Schema for nested data
schema = dict_schema({
    'users': list_schema(
        dict_schema({
            'name': str_schema(min_length=1),
            'age': int_schema(ge=0)
        })
    )
})

validator = SchemaValidator(schema)

try:
    data = {
        'users': [
            {'name': 'Alice', 'age': 25},  # Valid
            {'name': '', 'age': -5},       # Invalid name and age
            {'name': 'Charlie', 'age': 30}  # Valid
        ]
    }
    validator.validate_python(data)
except ValidationError as e:
    for error in e.errors():
        # Location shows exact path to error
        location_path = ' -> '.join(map(str, error['loc']))
        print(f"{location_path}: {error['msg']}")

# Output:
# users -> 1 -> name: String should have at least 1 character
# users -> 1 -> age: Input should be greater than or equal to 0

Custom Error Messages

from pydantic_core import PydanticCustomError, SchemaValidator, ValidationError
from pydantic_core.core_schema import with_info_plain_validator_function

def validate_username(value):
    """Custom validator with custom error messages."""
    if not isinstance(value, str):
        raise PydanticCustomError(
            'username_type',
            'Username must be a string, got {input_type}',
            {'input_type': type(value).__name__}
        )
    
    if len(value) < 3:
        raise PydanticCustomError(
            'username_too_short',
            'Username must be at least 3 characters long, got {input_length}',
            {'input_length': len(value)}
        )
    
    if not value.isalnum():
        raise PydanticCustomError(
            'username_invalid_chars',
            'Username must contain only letters and numbers'
        )
    
    return value

# Create schema with custom validator
schema = with_info_plain_validator_function(validate_username)
validator = SchemaValidator(schema)

try:
    validator.validate_python('ab!')  # Invalid characters
except ValidationError as e:
    for error in e.errors():
        print(f"Error: {error['msg']}")
        print(f"Type: {error['type']}")
        if 'ctx' in error:
            print(f"Context: {error['ctx']}")

# Output:
# Error: Username must contain only letters and numbers
# Type: username_invalid_chars

Known Error Types

from pydantic_core import PydanticKnownError, SchemaValidator, ValidationError
from pydantic_core.core_schema import with_info_plain_validator_function

def validate_even_number(value):
    """Validator using known error types."""
    if not isinstance(value, int):
        raise PydanticKnownError('int_type')
    
    if value % 2 != 0:
        raise PydanticKnownError(
            'int_multiple_of',
            {'multiple_of': 2}
        )
    
    return value

schema = with_info_plain_validator_function(validate_even_number)
validator = SchemaValidator(schema)

try:
    validator.validate_python(7)  # Odd number
except ValidationError as e:
    for error in e.errors():
        print(f"Error: {error['msg']}")
        print(f"Type: {error['type']}")
        print(f"Context: {error.get('ctx', {})}")

# Output will use the standard int_multiple_of error message

Serialization Error Handling

from pydantic_core import (
    SchemaSerializer, 
    PydanticSerializationError,
    PydanticSerializationUnexpectedValue
)
from pydantic_core.core_schema import dict_schema, str_schema

# Create serializer
schema = dict_schema({'name': str_schema()})
serializer = SchemaSerializer(schema)

try:
    # Try to serialize invalid data structure
    invalid_data = {'name': object()}  # object() is not serializable
    serializer.to_json(invalid_data)
except PydanticSerializationError as e:
    print(f"Serialization error: {e}")

# Handle with fallback
def fallback_handler(obj):
    return str(obj)

try:
    result = serializer.to_json(
        {'name': object()}, 
        fallback=fallback_handler
    )
    print(f"Serialized with fallback: {result}")
except PydanticSerializationError as e:
    print(f"Still failed: {e}")

Working with Error Information

from pydantic_core import list_all_errors

# Get information about all possible error types
all_errors = list_all_errors()

# Find specific error type information
string_errors = [
    error for error in all_errors 
    if error['type'].startswith('string_')
]

for error_info in string_errors[:3]:  # Show first 3 string errors
    print(f"Type: {error_info['type']}")
    print(f"Template: {error_info['message_template_python']}")
    print(f"Example: {error_info['example_message_python']}")
    if error_info['example_context']:
        print(f"Context: {error_info['example_context']}")
    print()

# Output shows error type information for string validation errors

Error Filtering and Analysis

from pydantic_core import SchemaValidator, ValidationError
from pydantic_core.core_schema import dict_schema, str_schema, int_schema, list_schema

# Complex schema for demonstration
schema = dict_schema({
    'personal': dict_schema({
        'name': str_schema(min_length=1),
        'age': int_schema(ge=0, le=120)
    }),
    'contacts': list_schema(
        dict_schema({
            'type': str_schema(),
            'value': str_schema(min_length=1)
        })
    )
})

validator = SchemaValidator(schema)

try:
    data = {
        'personal': {'name': '', 'age': -1},
        'contacts': [
            {'type': 'email', 'value': ''},
            {'type': 'phone', 'value': 'valid-phone'}
        ]
    }
    validator.validate_python(data)
except ValidationError as e:
    # Analyze errors by location
    errors_by_section = {}
    for error in e.errors():
        section = error['loc'][0] if error['loc'] else 'root'
        if section not in errors_by_section:
            errors_by_section[section] = []
        errors_by_section[section].append(error)
    
    for section, errors in errors_by_section.items():
        print(f"\nErrors in {section} section:")
        for error in errors:
            location = ' -> '.join(map(str, error['loc'][1:]))  # Skip section name
            print(f"  {location}: {error['msg']}")
    
    # Count errors by type
    error_types = {}
    for error in e.errors():
        error_type = error['type']
        error_types[error_type] = error_types.get(error_type, 0) + 1
    
    print(f"\nError type distribution:")
    for error_type, count in error_types.items():
        print(f"  {error_type}: {count}")

Install with Tessl CLI

npx tessl i tessl/pypi-pydantic-core

docs

error-handling.md

index.md

json-processing.md

schema-building.md

special-values.md

url-network.md

validation-serialization.md

tile.json