{"record":{"id":"73e4293a3f800f2f","repo":"deepset-ai/haystack","slug":"could-not-deserialize-type-type-str","errorCode":null,"errorMessage":"Could not deserialize type: {type_str}","messagePattern":"Could not deserialize type: (.+?)","errorType":"exception","errorClass":"DeserializationError","httpStatus":null,"severity":"error","filePath":"haystack/utils/type_serialization.py","lineNumber":285,"sourceCode":"            return _import_class_by_name(type_str)\n        except ImportError as e:\n            raise DeserializationError(str(e)) from e\n\n    # No module prefix, check builtins and typing.\n    # (None / NoneType / Ellipsis are handled at the top of this function, before they can reach the\n    # builtin type gate below which would refuse them for not being types.)\n    if hasattr(builtins, type_str):\n        resolved = getattr(builtins, type_str)\n        # This bare-name path never consults the allowlist. A type annotation must resolve to an\n        # actual type, so builtin functions like `eval`/`exec` are rejected while types pass.\n        _check_builtin_is_type(resolved, type_str)\n        return resolved\n\n    # Then check typing\n    if hasattr(typing, type_str):\n        return getattr(typing, type_str)\n\n    raise DeserializationError(f\"Could not deserialize type: {type_str}\")\n\n\ndef thread_safe_import(module_name: str) -> ModuleType:\n    \"\"\"\n    Import a module in a thread-safe manner.\n\n    Importing modules in a multi-threaded environment can lead to race conditions.\n    This function ensures that the module is imported in a thread-safe manner without having impact\n    on the performance of the import for single-threaded environments.\n\n    :param module_name: the module to import\n    \"\"\"\n    with _import_lock:\n        return importlib.import_module(module_name)\n\n\n@mark_deserialization_internal\ndef _import_class_by_name(fully_qualified_name: str) -> Any:","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/utils/type_serialization.py#L267-L303","documentation":"deserialize_type() falls back to looking up the name in builtins then in typing; if the bare (no-dot) name exists in neither, it raises DeserializationError('Could not deserialize type: {type_str}'). This is the terminal failure for unresolvable non-generic type names.","triggerScenarios":"deserialize_type('SomeCustomType') where the name has no module prefix and is not a builtin or typing name; typos like 'lits[int]' handled at the arg level; names like 'None' handled earlier so they never reach this.","commonSituations":"Serializing local classes defined in __main__/notebooks then deserializing elsewhere; typo'd type names in pipeline YAML; custom generic aliases that were not fully qualified.","solutions":["Fully qualify the type with its module path, e.g. 'myapp.models.MyType' instead of 'MyType'","Fix typos in the type string","Register/reference the type via an importable module instead of a locally defined class","Check whether the name exists: `hasattr(builtins, name) or hasattr(typing, name)`"],"exampleFix":"// before\ndeserialize_type(\"MyModel\")\n// after\ndeserialize_type(\"myapp.models.MyModel\")","handlingStrategy":"validation","validationCode":"import builtins, typing\ndef resolvable_bare_name(name):\n    if \".\" in name:\n        return True\n    return hasattr(builtins, name) or hasattr(typing, name)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always serialize types with their full module path, never bare local class names","Avoid serializing classes defined in notebooks or __main__","Validate type strings when writing pipeline YAML"],"tags":["python","deserialization","type-resolution","haystack"],"backgroundTag":"type-deserialization-failed","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}