pythonpydanticpydantic-v2

Custom ValidationError message for extra fields


I have defined a model using Pydantic V2 as follows:

from pydantic import BaseModel

class Data(BaseModel):
    valid: bool = False
    name: str | None = None
    model_config = ConfigDict(extra="forbid")

When I use this model to validate some data using model_validate with some extra field

Data.model_validate({"valid": True, "name": "John", "age": 30})

It raises this expected error:

pydantic_core._pydantic_core.ValidationError: 1 validation error for Data
age
  Extra inputs are not permitted [type=extra_forbidden, input_value=30, input_type=int]
    For further information visit https://errors.pydantic.dev/2.10/v/extra_forbidden

What I want to do is to replace the default message Extra inputs are not permitted by a custom message Unknown field.. To do so, I overwrote the model_validate method so I can customize my message. My model is defined now as follows:

from pydantic import BaseModel, ConfigDict
from pydantic_core import InitErrorDetails, ValidationError

class Data(BaseModel):
    valid: bool = False
    name: str | None = None
    model_config = ConfigDict(extra="forbid")  # Forbid extra fields

    @classmethod
    def model_validate(cls, value):
        try:
            return super().model_validate(value)
        except ValidationError as e:
            modified_errors = []
            for error in e.errors():
                if error['type'] == 'extra_forbidden':
                    modified_errors.append(
                        InitErrorDetails(
                            type=error['type'],
                            loc=error['loc'],
                            input=error['input'],
                            ctx={"error": "Unknown field."}  # Set custom message in `ctx`
                        )
                    )
                else:
                    modified_errors.append(error)

            raise ValidationError.from_exception_data(
                title="Validation failed",
                line_errors=modified_errors
            )

But, still when I run Data.model_validate({"valid": True, "name": "John", "age": 30}). It does not show the custom message "Unknown field.". What's wrong with my validator?


Solution

  • Try using a custom PydanticCustomError:

    from pydantic import BaseModel, ConfigDict, ValidationError
    from pydantic_core import PydanticCustomError, InitErrorDetails
    
    class Data(BaseModel):
        valid: bool = False
        name: str | None = None
        model_config = ConfigDict(extra="forbid")  # Forbid extra fields
    
        @classmethod
        def model_validate(cls, value):
            try:
                return super().model_validate(value)
            except ValidationError as e:
                modified_errors = []
                for error in e.errors():
                    if error['type'] == 'extra_forbidden':
                        custom_error = InitErrorDetails(
                            type=PydanticCustomError(
                                 "extra_forbidden", 
                                 "Unknown field."
                            ),
                            loc=error['loc'],
                            input=error['input'],
                        )
                        assert custom_error['msg'] == 'custom'
                        modified_errors.append(custom_error)
                    else:
                        modified_errors.append(error)
                raise ValidationError.from_exception_data(
                    title=cls.__name__,
                    line_errors=modified_errors
                )
    

    Example usage

    try:
        Data.model_validate({"valid": True, "name": "John", "age": 30})
    except ValidationError as e:
        print(e)  # Will now display the custom error message