pydantic/pydantic · error · TypeError
Unexpected type of exclude value
Error message
Unexpected type of exclude value {class_name} What it means
Raised by ValueItems._coerce_items when an `include`/`exclude` argument passed to model serialization (model_dump, model_dump_json, model_validate, etc.) is neither a Mapping nor an AbstractSet. The include/exclude API only accepts AbstractSet[int|str] (e.g. a set/frozenset of field names or indexes) or Mapping[int|str, Any] (a dict whose keys are field names/indexes and whose values recurse). Any other concrete type triggers this TypeError at serialization time. The {class_name} placeholder shows the offending value's class via getattr(items, '__class__', '???') — note it reads '__class__' (not '__class__.__name__'), so the rendered text is the raw class object, not a clean name.
Solutions
- If you want to exclude a flat group of fields, pass a set literal: model_dump(exclude={'field1','field2'}) instead of a list.
- If you build excludes from JSON/dynamic data, wrap with set(): model_dump(exclude=set(my_list)).
- For nested excludes use a dict with sets or Ellipsis as leaf values: model_dump(exclude={'outer': {'inner'}}) or model_dump(exclude={'outer': ...}).
- If you genuinely need order/selection of a list, convert each leaf to a set before passing to exclude/include.
Example fix
# before
model.model_dump(exclude=['password', 'token'])
# after
model.model_dump(exclude={'password', 'token'})
# or, from JSON data
model.model_dump(exclude=set(json_data['hidden_fields'])) Defensive patterns
Strategy: validation
Validate before calling
from collections.abc import Mapping, Set
def normalize_exclude(v):
"""Coerce include/exclude to a set or dict acceptable to pydantic v2."""
if v is None or v is True or v is ...:
return v
if isinstance(v, Mapping):
return {k: normalize_exclude(x) for k, x in v.items()}
if isinstance(v, (set, frozenset)):
return set(v)
if isinstance(v, (list, tuple)):
return set(v) # leaf list/tuple -> set
raise TypeError(f'Unsupported exclude type: {type(v).__name__}') Type guard
from collections.abc import Mapping, Set
def is_valid_exclude(v) -> bool:
if v is None or v is True or v is ...:
return True
if isinstance(v, Mapping):
return all(is_valid_exclude(x) for x in v.values())
return isinstance(v, (Set, list, tuple)) # caller must convert list/tuple Try / catch
# TypeError from _coerce_items is a programming error, not transient.
# Prefer pre-validation (above). If you must catch:
try:
data = model.model_dump(exclude=normalize_exclude(raw))
except TypeError as e:
raise ValueError(f'Bad exclude shape: {e}') from e Prevention
- Always pass sets (literals or set()) for flat field selection, never lists/tuples.
- When loading excludes from JSON, run set() over every array leaf.
- Centralize include/exclude construction in one helper so the shape is validated once.
- Add a unit test that asserts model_dump(exclude=...) accepts your dynamic exclude values.
When it happens
Trigger: Calling MyModel(...).model_dump(exclude=['field1','field2']) with a list instead of a set. Passing exclude=('a','b') (tuple, which is a Sequence but NOT an AbstractSet). Passing include=42 or exclude=some_custom_obj. Nesting a list inside a dict exclude: model_dump(exclude={'outer': ['inner']}) — the inner ['inner'] is a list and hits _coerce_items during recursive merge in ValueItems.merge.
Common situations: Developers coming from v1 who used lists for exclude and find v2 stricter. Building exclude structures dynamically and accidentally injecting a list. Confusing Sequence (list/tuple) with AbstractSet (set/frozenset) when reading type hints. Copying exclude values from JSON (which decodes arrays to lists, not sets).
Related errors
- Excluding fields from a sequence of sub-models or dicts…
- Unexpected type of exclude value for index
- Expected a class, got
- Expected ` ` but got ` ` with value `' '` - serialized…
- Expected ` ` but got ` ` with value `' '` - serialized…
AI-assisted analysis of pydantic/pydantic@cc13d1b8c9 (2026-08-11).
Data as JSON: /api/errors/76560f80a77d5538.
Report an issue: GitHub.
Appendix: source
Thrown at pydantic/_internal/_utils.py:288
merge_keys = list(base) + [k for k in override if k not in base]
merged: dict[int | str, Any] = {}
for k in merge_keys:
merged_item = cls.merge(base.get(k), override.get(k), intersect=intersect)
if merged_item is not None:
merged[k] = merged_item
return merged
@staticmethod
def _coerce_items(items: AbstractSetIntStr | MappingIntStrAny) -> MappingIntStrAny:
if isinstance(items, Mapping):
pass
elif isinstance(items, AbstractSet):
items = dict.fromkeys(items, ...) # type: ignore
else:
class_name = getattr(items, '__class__', '???')
raise TypeError(f'Unexpected type of exclude value {class_name}')
return items # type: ignore
@classmethod
def _coerce_value(cls, value: Any) -> Any:
if value is None or cls.is_true(value):
return value
return cls._coerce_items(value)
@staticmethod
def is_true(v: Any) -> bool:
return v is True or v is ...
def __repr_args__(self) -> _repr.ReprArgs:
return [(None, self._items)]
if TYPE_CHECKING:
View on GitHub (pinned to cc13d1b8c9)