deepset-ai/haystack · critical · DeserializationError
Refusing to deserialize an OutputAdapter with custom filters
Error message
Refusing to deserialize an OutputAdapter with custom filters while loading in safe mode. Custom filters are arbitrary callables that can execute during pipeline loading. If you trust the source of this data, load it with Pipeline.load(..., unsafe=True).
What it means
OutputAdapter.from_dict rejects serialized pipelines that carry custom_filters, because custom filters are arbitrary Python callables embedded in serialized data and would execute during pipeline loading — a code-execution vector when loading untrusted files. Safe mode refuses; only unsafe loading accepts them.
Source
Thrown at haystack/components/converters/output_adapter.py:187
:param data:
The dictionary to deserialize from.
:returns:
The deserialized component.
"""
init_params = data.get("init_parameters", {})
# `unsafe=True` swaps the Jinja sandbox for a NativeEnvironment that executes arbitrary code.
# Honor it from serialized data only when the whole pipeline is being loaded in unsafe mode;
# otherwise a hostile pipeline could disable the sandbox on its own in default safe mode.
if init_params.get("unsafe") and not _is_unsafe_deserialization():
raise DeserializationError(
"Refusing to deserialize an OutputAdapter with unsafe=True while loading in safe mode. "
"If you trust the source of this data, load it with Pipeline.load(..., unsafe=True)."
)
custom_filters = init_params.get("custom_filters", {})
if custom_filters and not _is_unsafe_deserialization():
raise DeserializationError(
"Refusing to deserialize an OutputAdapter with custom filters while loading in safe mode. "
"Custom filters are arbitrary callables that can execute during pipeline loading. "
"If you trust the source of this data, load it with Pipeline.load(..., unsafe=True)."
)
init_params["output_type"] = deserialize_type(init_params["output_type"])
if custom_filters:
init_params["custom_filters"] = {
name: deserialize_callable(filter_func) if filter_func else None
for name, filter_func in custom_filters.items()
}
return default_from_dict(cls, data)
View on GitHub (pinned to e318778c9b)
Solutions
- Load with Pipeline.loads(data, unsafe=True) only if you trust the pipeline source
- Recreate the OutputAdapter in code with the filters registered programmatically instead of loading them from the file
- Strip custom_filters from the YAML and re-add filters at runtime after loading
Example fix
// before
pipeline = Pipeline.loads(data_with_filters)
// after
pipeline = Pipeline.loads(sanitized_data)
adapter = pipeline.get_component("my_adapter")
adapter.custom_filters["my_filter"] = my_filter # re-register locally Defensive patterns
Strategy: try-catch
Validate before calling
import yaml
def has_custom_filters(path):
data = yaml.safe_load(open(path))
return any(
c.get("type") == "OutputAdapter" and c.get("init_parameters", {}).get("custom_filters")
for c in data.get("components", []).values()
) Try / catch
try:
pipeline = Pipeline.load(path)
except DeserializationError as e:
if "custom filters" in str(e):
pipeline = rebuild_adapter_in_code(path) # register filters locally
else:
raise Prevention
- Serialize pipelines without embedding callables; register filters in code
- Only use unsafe=True loading for pipelines you authored
- Share pipeline templates as code, not as serialized artifacts with filters
When it happens
Trigger: Pipeline.load/loads in default safe mode on a pipeline file whose OutputAdapter init_parameters include a non-empty custom_filters dict.
Common situations: Sharing pipelines between teams where one side registered custom Jinja filters; stored pipeline artifacts that reference local filter functions; CI loading contributed pipelines.
Related errors
- Refusing to deserialize an OutputAdapter with unsafe=True wh
- Missing 'type' in serialization data
- Refusing to deserialize '{handle}': it resolves to '{name}',
- 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/8290102199c170f2.
Report an issue: GitHub.