deepset-ai/haystack · error · DeserializationError

Class '{data['type']}' can't be deserialized as '{cls.__name

Error message

Class '{data['type']}' can't be deserialized as '{cls.__name__}'

What it means

The serialized 'type' field must exactly match the fully-qualified name of the class being deserialized. default_from_dict() raises this when the data's 'type' points to a different class than the one from_dict() was called on, preventing construction of the wrong object from mislabeled data.

Source

Thrown at haystack/core/serialization.py:301

    :param cls:
        The class to be used for deserialization.
    :param data:
        The serialized data.
    :returns:
        The deserialized object.

    :raises DeserializationError:
        If the `type` field in `data` is missing or it doesn't match the type of `cls`.
    """
    # Copy so that replacing serialized sub-objects (Secret/ComponentDevice/nested components) with their
    # deserialized instances below does not mutate the caller's ``data`` dict in place. Without this, a second
    # deserialization of the same dict would receive already-parsed objects instead of their serialized form.
    init_params = dict(data.get("init_parameters", {}))
    if "type" not in data:
        raise DeserializationError("Missing 'type' in serialization data")
    if data["type"] != generate_qualified_class_name(cls):
        raise DeserializationError(f"Class '{data['type']}' can't be deserialized as '{cls.__name__}'")

    valid_init_param_names = _init_parameter_names(cls)

    # Automatically detect and deserialize objects with from_dict methods
    for key, value in init_params.items():
        if isinstance(value, dict) and "type" in value:
            type_value = value.get("type")
            # Special handling for Secret (type == "env_var")
            if type_value == "env_var":
                init_params[key] = Secret.from_dict(value)
            # Special handling for ComponentDevice (type == "single" or "multiple")
            elif _is_serialized_component_device(value):
                init_params[key] = ComponentDevice.from_dict(value)
            # If type looks like a fully qualified class name, try to import it and deserialize
            elif isinstance(type_value, str) and "." in type_value:
                # Reject before importing if the parent class does not accept this parameter.
                # This blocks YAML that smuggles untrusted classes into unused parameter slots.
                if valid_init_param_names is not None and key not in valid_init_param_names:

View on GitHub (pinned to e318778c9b)

Solutions

  1. Update data['type'] to the current fully-qualified class name.
  2. Re-export the pipeline from an environment with the original component installed.
  3. Check the haystack version and migrate serialized configs to the new class paths.
  4. Ensure from_dict is called on the correct class rather than a sibling class.

Example fix

// before
{"type": "haystack.nodes.retriever.sparse.ElasticsearchRetriever", ...}

// after
{"type": "haystack.components.retrievers.in_memory.InMemoryBM25Retriever", ...}
Defensive patterns

Strategy: validation

Validate before calling

from haystack.core.serialization import generate_qualified_class_name
assert data.get("type") == generate_qualified_class_name(MyComponent), data.get("type")

Type guard

def matches_class(data: dict, cls) -> bool:
    from haystack.core.serialization import generate_qualified_class_name
    return isinstance(data, dict) and data.get("type") == generate_qualified_class_name(cls)

Try / catch

from haystack.core.errors import DeserializationError
try:
    comp = MyComponent.from_dict(data)
except DeserializationError as e:
    if "can't be deserialized as" in str(e):
        data["type"] = generate_qualified_class_name(MyComponent)
        comp = MyComponent.from_dict(data)

Prevention

When it happens

Trigger: Calling SomeComponent.from_dict(data) where data['type'] is a different class (e.g. renamed or moved class, copy-pasted serialized block, or loading a component dict into the wrong class).

Common situations: Class renamed/moved between haystack versions so old serialized pipelines carry the old qualified name; hand-copied YAML with a stale type string; custom component refactors changing module paths.

Related errors


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