deepset-ai/haystack · error · DeserializationError

Could not import '{type_str}' as it may not exist or is not

Error message

Could not import '{type_str}' as it may not exist or is not a valid class

What it means

Actually raised inside _import_class_by_name's guard chain (the SOURCE shown is the except clause in deserialize_type): when importing a dotted type path fails, _import_class_by_name raises ImportError('Could not import ...'), but in this code path the failure is reported as 'Could not import \'{type_str}\' as it may not exist or is not a valid class'. It indicates the serialized dotted type could not be resolved to an importable class in this environment.

Source

Thrown at haystack/utils/type_serialization.py:269

        # arguments.
        if main_type is typing.Literal:
            return typing.Literal[ast.literal_eval(f"({generics_str},)")]

        generic_args = [_deserialize_type_arg(arg) for arg in _parse_generic_args(generics_str)]

        # Reconstruct
        try:
            return main_type[tuple(generic_args) if len(generic_args) > 1 else generic_args[0]]
        except (TypeError, AttributeError) as e:
            raise DeserializationError(f"Could not apply arguments {generic_args} to type {main_type}") from e

    # Handle non-generic types
    # First, check if there's a module prefix
    if "." in type_str:
        try:
            return _import_class_by_name(type_str)
        except ImportError as e:
            raise DeserializationError(str(e)) from e

    # No module prefix, check builtins and typing.
    # (None / NoneType / Ellipsis are handled at the top of this function, before they can reach the
    # builtin type gate below which would refuse them for not being types.)
    if hasattr(builtins, type_str):
        resolved = getattr(builtins, type_str)
        # This bare-name path never consults the allowlist. A type annotation must resolve to an
        # actual type, so builtin functions like `eval`/`exec` are rejected while types pass.
        _check_builtin_is_type(resolved, type_str)
        return resolved

    # Then check typing
    if hasattr(typing, type_str):
        return getattr(typing, type_str)

    raise DeserializationError(f"Could not deserialize type: {type_str}")

View on GitHub (pinned to e318778c9b)

Solutions

  1. Install the missing package or fix the environment so the dotted path imports
  2. Update the serialized type string to the current class path
  3. Manually run `import some.module; some.module.SomeClass` to see the true cause
  4. Check the accompanying logger.exception traceback for the underlying ImportError/AttributeError

Example fix

// before
deserialize_type("haystack.nodes.retriever.dense.DensePassageRetriever")  # 1.x path
// after
deserialize_type("haystack.components.retrievers.in_memory.InMemoryEmbeddingRetriever")  # 2.x path
Defensive patterns

Strategy: try-catch

Validate before calling

import importlib
def dotted_importable(path):
    try:
        importlib.import_module(path.rsplit(".", 1)[0])
        return True
    except ImportError:
        return False

Try / catch

from haystack.utils import DeserializationError
try:
    t = deserialize_type(type_str)
except DeserializationError:
    t = None  # fall back or re-serialize with current library

Prevention

When it happens

Trigger: deserialize_type('some.module.SomeClass') where the module is absent, the class name changed, or the resolved attribute is not a class (fails the class-validity check); loading pipelines serialized against different code.

Common situations: Missing optional dependencies; refactor/renames between haystack versions; sharing serialized pipeline YAML across projects with different component packages.

Related errors


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