deepset-ai/haystack · error · SerializationError

Serialization of instance methods is not supported.

Error message

Serialization of instance methods is not supported.

What it means

serialize_callable refuses to serialize bound instance methods: it inspects the argspec and, if the first argument is 'self', raises SerializationError. Serialized callables must be importable by fully qualified path, and a bound method depends on a specific instance that cannot be reconstructed from a string.

Source

Thrown at haystack/utils/callable_serialization.py:40

from haystack.utils.type_serialization import thread_safe_import

logger = logging.getLogger(__name__)


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`.

View on GitHub (pinned to e318778c9b)

Solutions

  1. Use a module-level function or staticmethod/classmethod instead of an instance method
  2. Wrap the method call in a module-level function that constructs the object internally
  3. Serialize a class method or plain function referenced by its import path
  4. Make the callback a callable class (with __call__) whose class is importable, if supported

Example fix

// before
class Pipe:
    def split(self, text): ...
TextSplitter(splitting_function=self.split)
// after
# module-level function
# mymodule/callbacks.py
def split(text): ...
TextSplitter(splitting_function=split)
Defensive patterns

Strategy: validation

Validate before calling

import inspect

def is_instance_method(fn) -> bool:
    try:
        spec = inspect.getfullargspec(fn)
        return bool(spec.args and spec.args[0] == "self")
    except TypeError:
        return False

# call before passing to a component: is_instance_method(my_callback)

Type guard

import inspect
from collections.abc import Callable

def is_serializable_callable(fn: Callable) -> bool:
    try:
        qualname = getattr(fn, "__qualname__", "")
        spec = inspect.getfullargspec(fn)
        bound_self = bool(spec.args and spec.args[0] == "self")
        return not bound_self and "<lambda>" not in qualname and "<locals>" not in qualname
    except TypeError:
        return False

Try / catch

try:
    comp.to_dict()
except SerializationError as e:
    logger.error("callable cannot be serialized: %s", e)
    raise

Prevention

When it happens

Trigger: Passing an instance method (e.g. self.preprocess or obj.splitter_func) to a component parameter that gets serialized via to_dict, e.g. TextSplitter(splitting_function=self.my_method) then pipeline.dumps().

Common situations: Building pipelines programmatically where a callback is a method of a class instance; converting a working in-memory pipeline to YAML for persistence.

Related errors


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