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

  1. If you want to exclude a flat group of fields, pass a set literal: model_dump(exclude={'field1','field2'}) instead of a list.
  2. If you build excludes from JSON/dynamic data, wrap with set(): model_dump(exclude=set(my_list)).
  3. For nested excludes use a dict with sets or Ellipsis as leaf values: model_dump(exclude={'outer': {'inner'}}) or model_dump(exclude={'outer': ...}).
  4. 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

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


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)