deepset-ai/haystack · error · SerializationError

Component '{name}' of type '{type(component).__name__}' has

Error message

Component '{name}' of type '{type(component).__name__}' has a non-string key in the serialized data.

What it means

Serialized component data must have string keys in every dict (JSON requirement). Haystack raises this during validation of a component's to_dict() output when any dict at any level has a non-string key (e.g. int, enum, tuple). This prevents data loss when the dict is written to JSON/YAML.

Source

Thrown at haystack/core/serialization.py:111

    # Ensure that only basic Python types are used in the serde data.
    def is_allowed_type(obj: Any) -> bool:
        return isinstance(obj, (str, int, float, bool, list, dict, set, tuple, type(None)))

    def check_iterable(iterable: Iterable[Any]) -> None:
        for v in iterable:
            if not is_allowed_type(v):
                raise SerializationError(
                    f"Component '{name}' of type '{type(component).__name__}' has an unsupported value "
                    f"of type '{type(v).__name__}' in the serialized data."
                )
            if isinstance(v, (list, set, tuple)):
                check_iterable(v)
            elif isinstance(v, dict):
                check_dict(v)

    def check_dict(d: dict[str, Any]) -> None:
        if any(not isinstance(k, str) for k in d):
            raise SerializationError(
                f"Component '{name}' of type '{type(component).__name__}' has a non-string key in the serialized data."
            )

        for k, v in d.items():
            if not is_allowed_type(v):
                raise SerializationError(
                    f"Component '{name}' of type '{type(component).__name__}' has an unsupported value "
                    f"of type '{type(v).__name__}' in the serialized data under key '{k}'."
                )
            if isinstance(v, (list, set, tuple)):
                check_iterable(v)
            elif isinstance(v, dict):
                check_dict(v)

    check_dict(data)


def generate_qualified_class_name(cls: type[object]) -> str:

View on GitHub (pinned to e318778c9b)

Solutions

  1. Fix the component's to_dict() to convert keys to strings (e.g. str(key)).
  2. Update from_dict() to convert keys back to their original type on deserialization.
  3. Change the init parameter so keys are strings at construction time.
  4. Use enum .name or .value as the key instead of the enum object.

Example fix

// before
{"init_parameters": {"rates": {1: 0.5, 2: 0.3}}}

// after
{"init_parameters": {"rates": {"1": 0.5, "2": 0.3}}}  # from_dict converts keys back to int
Defensive patterns

Strategy: validation

Validate before calling

def check_keys(obj) -> list:
    bad = []
    if isinstance(obj, dict):
        bad += [k for k in obj if not isinstance(k, str)]
        for v in obj.values(): bad += check_keys(v)
    elif isinstance(obj, (list, tuple, set)):
        for v in obj: bad += check_keys(v)
    return bad

Type guard

def str_keys_only(d) -> bool:
    return isinstance(d, dict) and all(isinstance(k, str) for k in d)

Try / catch

from haystack.core.errors import SerializationError
try:
    pipeline.dumps()
except SerializationError as e:
    if "non-string key" in str(e): ...
raise

When it happens

Trigger: Calling pipeline.dumps() when a component's serialized init_parameters contain a dict keyed by ints or enum members, e.g. {1: "a"} or {MyEnum.X: 1}.

Common situations: Components that use enums or integer IDs as dict keys; passing a raw dict with non-str keys as an init parameter; mapping objects built from {int: str} lookups.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/f77f24ad9e2b20a7. Report an issue: GitHub.