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?
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
)
try:
Data.model_validate({"valid": True, "name": "John", "age": 30})
except ValidationError as e:
print(e) # Will now display the custom error message