deepset-ai/haystack · error · DeserializationError
Could not deserialize type: {type_str}
Error message
Could not deserialize type: {type_str} What it means
deserialize_type() falls back to looking up the name in builtins then in typing; if the bare (no-dot) name exists in neither, it raises DeserializationError('Could not deserialize type: {type_str}'). This is the terminal failure for unresolvable non-generic type names.
Source
Thrown at haystack/utils/type_serialization.py:285
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}")
def thread_safe_import(module_name: str) -> ModuleType:
"""
Import a module in a thread-safe manner.
Importing modules in a multi-threaded environment can lead to race conditions.
This function ensures that the module is imported in a thread-safe manner without having impact
on the performance of the import for single-threaded environments.
:param module_name: the module to import
"""
with _import_lock:
return importlib.import_module(module_name)
@mark_deserialization_internal
def _import_class_by_name(fully_qualified_name: str) -> Any:View on GitHub (pinned to e318778c9b)
Solutions
- Fully qualify the type with its module path, e.g. 'myapp.models.MyType' instead of 'MyType'
- Fix typos in the type string
- Register/reference the type via an importable module instead of a locally defined class
- Check whether the name exists: `hasattr(builtins, name) or hasattr(typing, name)`
Example fix
// before
deserialize_type("MyModel")
// after
deserialize_type("myapp.models.MyModel") Defensive patterns
Strategy: validation
Validate before calling
import builtins, typing
def resolvable_bare_name(name):
if "." in name:
return True
return hasattr(builtins, name) or hasattr(typing, name) Prevention
- Always serialize types with their full module path, never bare local class names
- Avoid serializing classes defined in notebooks or __main__
- Validate type strings when writing pipeline YAML
When it happens
Trigger: deserialize_type('SomeCustomType') where the name has no module prefix and is not a builtin or typing name; typos like 'lits[int]' handled at the arg level; names like 'None' handled earlier so they never reach this.
Common situations: Serializing local classes defined in __main__/notebooks then deserializing elsewhere; typo'd type names in pipeline YAML; custom generic aliases that were not fully qualified.
Related errors
- Refusing to deserialize an OutputAdapter with unsafe=True wh
- Refusing to deserialize an OutputAdapter with custom filters
- Missing 'type' in serialization data
- Failed to deserialize data '{payload}' into Pydantic model '
- Value '{payload}' is not a valid member of Enum '{value_type
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/73e4293a3f800f2f.
Report an issue: GitHub.