deepset-ai/haystack · error · DeserializationError
Could not import '{callable_handle}' as a module or callable
Error message
Could not import '{callable_handle}' as a module or callable. What it means
deserialize_callable exhausted every resolution strategy against the module allowlist and still could not import the handle, so after emitting the standard allowlist error it raises DeserializationError. Neither the top-level module nor any dotted path could be resolved to a callable.
Source
Thrown at haystack/utils/callable_serialization.py:171
# The module check also does not stop import primitives that live inside an allowlisted
# namespace (e.g. `haystack...thread_safe_import`), which are gateways to code execution
# equivalent to the denied builtin `__import__`. Block them too.
_check_not_denied_callable(attr_value, callable_handle)
# Refuse the deserializer's own machinery — the allowlist-administration function
# (`allow_deserialization_module`) and the resolution helpers (`deserialize_callable`,
# `deserialize_type`, `import_class_by_name`). They live in the allowlisted `haystack`
# namespace, so the module checks above admit them, but resolving them from serialized data
# lets a hostile pipeline register them as Jinja custom filters, disarm the allowlist with
# `'*'`, and then resolve and invoke arbitrary callables such as `os.system`.
_check_not_deserialization_internal(attr_value, callable_handle)
return attr_value
# Nothing on the allowlist was importable. Surface the standard allowlist error when the
# top-level module is untrusted; otherwise report a plain resolution failure.
_check_module_allowed(callable_handle)
raise DeserializationError(f"Could not import '{callable_handle}' as a module or callable.")
View on GitHub (pinned to e318778c9b)
Solutions
- Install the missing package or add your module to sys.path/PYTHONPATH
- Ensure the module is trusted/allowlisted for haystack deserialization (configure the allowlist mechanism)
- Fix typos in the serialized callable handle
- Verify importability with importlib.import_module on the top-level module
Example fix
// before python -c "import my_custom_components" # ModuleNotFoundError // after pip install -e . # or export PYTHONPATH=/path/to/project
Defensive patterns
Strategy: try-catch
Validate before calling
import importlib
def module_importable(handle: str) -> bool:
try:
importlib.import_module(handle.split(".")[0])
return True
except ImportError:
return False Try / catch
try:
pipeline = Pipeline.loads(yaml_str)
except DeserializationError as e:
if "Could not import" in str(e):
handle = extract_handle(str(e))
logger.error("install missing package or allowlist module for %s", handle)
raise Prevention
- Ensure all packages referenced by a pipeline are installed in the target environment
- Add custom component modules to the deserialization allowlist when required
- Keep PYTHONPATH/sys.path correct in deployment environments
- Prefer importing haystack-provided component paths over ad-hoc handles
When it happens
Trigger: from_dict/deserialize_callable with a handle whose module is not importable (not installed, wrong PYTHONPATH) or not on the deserialization allowlist, or a malformed dotted path.
Common situations: Loading a pipeline referencing a third-party package not installed in the current environment; custom components module not on sys.path; module blocked by haystack's safe-deserialization allowlist; typos in module names.
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/f2053c2c81e462c1.
Report an issue: GitHub.