deepset-ai/haystack · error · SerializationError
Serialization of lambdas is not supported.
Error message
Serialization of lambdas is not supported.
What it means
serialize_callable inspects __qualname__ and raises SerializationError when it contains '<lambda>', because a lambda has no importable module path and cannot be reconstructed by deserialize_callable. Only importable, named callables can be serialized.
Source
Thrown at haystack/utils/callable_serialization.py:45
def serialize_callable(callable_handle: Callable) -> str:
"""
Serializes a callable to its full path.
:param callable_handle: The callable to serialize
:return: The full path of the callable
"""
try:
full_arg_spec = inspect.getfullargspec(callable_handle)
is_instance_method = bool(full_arg_spec.args and full_arg_spec.args[0] == "self")
except TypeError:
is_instance_method = False
if is_instance_method:
raise SerializationError("Serialization of instance methods is not supported.")
# __qualname__ contains the fully qualified path we need for classmethods and staticmethods
qualname = getattr(callable_handle, "__qualname__", "")
if "<lambda>" in qualname:
raise SerializationError("Serialization of lambdas is not supported.")
if "<locals>" in qualname:
raise SerializationError("Serialization of nested functions is not supported.")
name = qualname or callable_handle.__name__
# Get the full package path of the function
module = inspect.getmodule(callable_handle)
if module is not None:
full_path = f"{module.__name__}.{name}"
else:
full_path = name
# Serialization succeeds, but a denied builtin (e.g. `eval`) won't reload without `unsafe=True`.
if _is_denied_builtin(callable_handle):
logger.warning(
"Serialized callable '{full_path}' is a builtin that is blocked during deserialization; "
"the resulting pipeline will only be loadable with unsafe=True.",
full_path=full_path,View on GitHub (pinned to e318778c9b)
Solutions
- Replace the lambda with a named module-level function
- Define the logic in a small helper function in an importable module
- If configuration-only customization is needed, use a supported parameter instead of a callable
Example fix
// before TextSplitter(splitting_function=lambda t: t.lower()) // after # mymodule/helpers.py def lowercase(t): return t.lower() TextSplitter(splitting_function=lowercase)
Defensive patterns
Strategy: validation
Validate before calling
def is_lambda(fn) -> bool:
return getattr(fn, "__name__", "") == "<lambda>"
# reject before passing to component Type guard
import types
from collections.abc import Callable
def is_named_module_level_function(fn: Callable) -> bool:
return isinstance(fn, types.FunctionType) and "<" not in fn.__qualname__ Try / catch
try:
serialized = component.to_dict()
except SerializationError as e:
if "lambda" in str(e):
logger.error("replace lambda with a named module-level function")
raise Prevention
- Lint against lambdas in component init parameters
- Replace lambdas with named helpers in an importable module
- Review notebooks/scripts before saving pipelines to YAML
When it happens
Trigger: Passing a lambda as a callable parameter (e.g. TextSplitter(splitting_function=lambda t: t.lower())) and then calling to_dict or pipeline.dumps().
Common situations: Quick inline lambdas used in scripts or notebooks that later get saved to YAML; pipeline configs built at runtime.
Related errors
- Serialization of instance methods is not supported.
- Serialization of nested functions is not supported.
- Component '{name}' of type '{type(component).__name__}' has
- Component '{name}' of type '{type(component).__name__}' has
- Component '{name}' of type '{type(component).__name__}' has
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/0365c7bfd9071c45.
Report an issue: GitHub.