pydantic/pydantic · error · PydanticSerializationUnexpectedValue
Expected ` ` but got ` ` with value `' '` - serialized…
Error message
Expected `{tp}` but got `{type(path)}` with value `'{path}'` - serialized value may not be as expected. What it means
PydanticSerializationUnexpectedValue raised in ser_path, the serializer pydantic attaches to path types. At serialization time it checks isinstance(path, (tp, str)); if the value held by the field is neither the declared path type (tp) nor a str, it raises this. Like error 42 for IPs, this indicates the field was populated with a value of the wrong type (e.g. via model_construct() or direct __dict__ mutation), so JSON serialization would emit an unexpected representation.
Solutions
- Construct the model via Model.model_validate(data) instead of model_construct() so the path field is coerced to a real path object.
- If model_construct() is required, pre-coerce: pathlib.Path(value) before assignment.
- Make the field type a Union (pathlib.Path | None) and ensure None is handled in serialization.
- Add a model_validator(mode='before') that normalizes raw values to paths.
Example fix
// before
m = Cfg.model_construct(p='/tmp/x') # stored as str, not Path
m.model_dump_json() # may raise if tp is PurePath and value is str-only edge
// after
m = Cfg.model_validate({'p': '/tmp/x'}) # validated to PurePath
m.model_dump_json() Defensive patterns
Strategy: validation
Validate before calling
import pathlib
def coerce_path(value):
if isinstance(value, (pathlib.PurePath, str)):
return value
if value is None:
return value
return pathlib.Path(value)
# data['p'] = coerce_path(data['p']); then use model_validate, not model_construct Type guard
import pathlib
def is_path_or_str(value, tp=pathlib.PurePath) -> bool:
return isinstance(value, (tp, str)) Try / catch
from pydantic_core import PydanticSerializationUnexpectedValue
try:
obj.model_dump_json()
except PydanticSerializationUnexpectedValue:
obj = M.model_validate(obj.model_dump()) # re-coerce
obj.model_dump_json() Prevention
- Prefer model_validate() over model_construct() for models with path fields.
- Add a model_validator(mode='before') that coerces raw values to paths.
- Test JSON serialization on models constructed from raw input.
- Document that path fields must hold path objects or strings.
When it happens
Trigger: model_construct(p=42) on a pathlib.Path field then model_dump_json(); assigning an int or dict to a path field after validation; a custom validator returning a non-path, non-str object; ORM integration that returns a raw column value into a path field without coercion.
Common situations: Using model_construct() for speed and feeding DB rows whose path column is None or an int; mutating the field post-validation; deserializing from msgpack/protobuf where the path is a bytes blob that was not decoded.
Related errors
- Expected ` ` but got ` ` with value `' '` - serialized…
- Excluding fields from a sequence of sub-models or dicts…
- Expected ` ` but got ` ` with value `' '` - serialized…
- path_type
- Unexpected type of exclude value for index
AI-assisted analysis of pydantic/pydantic@cc13d1b8c9 (2026-08-11).
Data as JSON: /api/errors/848b963a6af22ce5.
Report an issue: GitHub.
Appendix: source
Thrown at pydantic/_internal/_generate_schema.py:619
try:
if path_type is bytes:
if isinstance(input_value, bytes):
try:
input_value = input_value.decode()
except UnicodeDecodeError as e:
raise PydanticCustomError('bytes_type', 'Input must be valid bytes') from e
else:
raise PydanticCustomError('bytes_type', 'Input must be bytes')
elif not isinstance(input_value, str):
raise PydanticCustomError('path_type', 'Input is not a valid path')
return path_constructor(input_value) # type: ignore
except TypeError as e:
raise PydanticCustomError('path_type', 'Input is not a valid path') from e
def ser_path(path: Any, info: core_schema.SerializationInfo) -> str | os.PathLike[Any]:
if not isinstance(path, (tp, str)):
raise PydanticSerializationUnexpectedValue(
f"Expected `{tp}` but got `{type(path)}` with value `'{path}'` - serialized value may not be as expected."
)
if info.mode == 'python':
return path
return str(path)
instance_schema = core_schema.json_or_python_schema(
json_schema=core_schema.no_info_after_validator_function(path_validator, lax_inner_schema),
python_schema=core_schema.is_instance_schema(tp),
)
schema = core_schema.lax_or_strict_schema(
lax_schema=core_schema.union_schema(
[
instance_schema,
core_schema.no_info_after_validator_function(path_validator, strict_inner_schema),
],
custom_error_type='path_type',View on GitHub (pinned to cc13d1b8c9)