{"record":{"id":"4ee13747a5ab5c09","repo":"deepset-ai/haystack","slug":"serialization-of-instance-methods-is-not-supported","errorCode":null,"errorMessage":"Serialization of instance methods is not supported.","messagePattern":"Serialization of instance methods is not supported\\.","errorType":"exception","errorClass":"SerializationError","httpStatus":null,"severity":"error","filePath":"haystack/utils/callable_serialization.py","lineNumber":40,"sourceCode":"from haystack.utils.type_serialization import thread_safe_import\n\nlogger = logging.getLogger(__name__)\n\n\ndef serialize_callable(callable_handle: Callable) -> str:\n    \"\"\"\n    Serializes a callable to its full path.\n\n    :param callable_handle: The callable to serialize\n    :return: The full path of the callable\n    \"\"\"\n    try:\n        full_arg_spec = inspect.getfullargspec(callable_handle)\n        is_instance_method = bool(full_arg_spec.args and full_arg_spec.args[0] == \"self\")\n    except TypeError:\n        is_instance_method = False\n    if is_instance_method:\n        raise SerializationError(\"Serialization of instance methods is not supported.\")\n\n    # __qualname__ contains the fully qualified path we need for classmethods and staticmethods\n    qualname = getattr(callable_handle, \"__qualname__\", \"\")\n    if \"<lambda>\" in qualname:\n        raise SerializationError(\"Serialization of lambdas is not supported.\")\n    if \"<locals>\" in qualname:\n        raise SerializationError(\"Serialization of nested functions is not supported.\")\n\n    name = qualname or callable_handle.__name__\n\n    # Get the full package path of the function\n    module = inspect.getmodule(callable_handle)\n    if module is not None:\n        full_path = f\"{module.__name__}.{name}\"\n    else:\n        full_path = name\n\n    # Serialization succeeds, but a denied builtin (e.g. `eval`) won't reload without `unsafe=True`.","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/utils/callable_serialization.py#L22-L58","documentation":"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.","triggerScenarios":"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().","commonSituations":"Building pipelines programmatically where a callback is a method of a class instance; converting a working in-memory pipeline to YAML for persistence.","solutions":["Use a module-level function or staticmethod/classmethod instead of an instance method","Wrap the method call in a module-level function that constructs the object internally","Serialize a class method or plain function referenced by its import path","Make the callback a callable class (with __call__) whose class is importable, if supported"],"exampleFix":"// before\nclass Pipe:\n    def split(self, text): ...\nTextSplitter(splitting_function=self.split)\n// after\n# module-level function\n# mymodule/callbacks.py\ndef split(text): ...\nTextSplitter(splitting_function=split)","handlingStrategy":"validation","validationCode":"import inspect\n\ndef is_instance_method(fn) -> bool:\n    try:\n        spec = inspect.getfullargspec(fn)\n        return bool(spec.args and spec.args[0] == \"self\")\n    except TypeError:\n        return False\n\n# call before passing to a component: is_instance_method(my_callback)","typeGuard":"import inspect\nfrom collections.abc import Callable\n\ndef is_serializable_callable(fn: Callable) -> bool:\n    try:\n        qualname = getattr(fn, \"__qualname__\", \"\")\n        spec = inspect.getfullargspec(fn)\n        bound_self = bool(spec.args and spec.args[0] == \"self\")\n        return not bound_self and \"<lambda>\" not in qualname and \"<locals>\" not in qualname\n    except TypeError:\n        return False","tryCatchPattern":"try:\n    comp.to_dict()\nexcept SerializationError as e:\n    logger.error(\"callable cannot be serialized: %s\", e)\n    raise","preventionTips":["Always pass module-level functions as callable component parameters","Never pass bound methods or lambdas into serialized components","Round-trip test (dumps/loads) pipelines that use callbacks in CI"],"tags":["python","serialization","callable","haystack"],"backgroundTag":"unserializable-callable","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}