{"record":{"id":"45e53ea12cc2f07d","repo":"deepset-ai/haystack","slug":"failed-to-create-json-schema-for-function-functi","errorCode":null,"errorMessage":"Failed to create JSON schema for function '{function.__name__}'","messagePattern":"Failed to create JSON schema for function '(.+?)'","errorType":"exception","errorClass":"SchemaGenerationError","httpStatus":null,"severity":"error","filePath":"haystack/tools/from_function.py","lineNumber":170,"sourceCode":"\n        # Skip Callable types since Pydantic cannot generate JSON schemas for them\n        if _contains_callable_type(param.annotation):\n            continue\n\n        # if the parameter has not a default value, Pydantic requires an Ellipsis (...)\n        # to explicitly indicate that the parameter is required\n        default = param.default if param.default is not param.empty else ...\n        fields[param_name] = (param.annotation, default)\n\n        if hasattr(param.annotation, \"__metadata__\"):\n            descriptions[param_name] = param.annotation.__metadata__[0]\n\n    # create Pydantic model and generate JSON schema\n    try:\n        model = create_model(function.__name__, **fields)\n        schema = model.model_json_schema()\n    except Exception as e:\n        raise SchemaGenerationError(f\"Failed to create JSON schema for function '{function.__name__}'\") from e\n\n    # we don't want to include title keywords in the schema, as they contain redundant information\n    # there is no programmatic way to prevent Pydantic from adding them, so we remove them later\n    # see https://github.com/pydantic/pydantic/discussions/8504\n    _remove_title_from_schema(schema)\n\n    # add parameters descriptions to the schema\n    for param_name, param_description in descriptions.items():\n        if param_name in schema[\"properties\"]:\n            schema[\"properties\"][param_name][\"description\"] = param_description\n\n    is_async = inspect.iscoroutinefunction(function)\n\n    return Tool(\n        name=name or function.__name__,\n        description=tool_description,\n        parameters=schema,\n        function=None if is_async else function,","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/tools/from_function.py#L152-L188","documentation":"Raised as SchemaGenerationError when Pydantic's create_model(...).model_json_schema() fails for a function being converted into a Tool via create_tool_from_function. Unlike error 421 (missing annotation), this means annotations exist but at least one cannot be turned into a JSON schema — typically unsupported or malformed types. The original Pydantic exception is chained as __cause__.","triggerScenarios":"@tool or create_tool_from_function(fn) where a parameter annotation is a type Pydantic cannot schema-ize: bare Callable, arbitrary class instances, invalid generic parameterization, or unresolvable string forward references.","commonSituations":"Wrapping functions that take client objects or callbacks; using exotic typing constructs (e.g. recursive types without proper definition) in signatures; importing a tool function after a refactor broke a forward reference.","solutions":["Check the chained __cause__ exception to identify the failing parameter type","Replace unsupported annotations (Callable, custom classes) with JSON-serializable types (str, int, float, bool, list, dict, Enum, BaseModel)","Ensure any forward references resolve at call time (import the types before tool creation)","Fix generic annotations, e.g. use list[str] instead of a partially parameterized or erroneous generic"],"exampleFix":"// before\ndef run_query(db: Connection, cb: Callable) -> dict:\n    ...\n\n// after\ndef run_query(query: str) -> dict:\n    ...","handlingStrategy":"try-catch","validationCode":"from typing import get_type_hints\n\ndef validate_schemaable(fn) -> str | None:\n    try:\n        hints = get_type_hints(fn)\n    except Exception as e:\n        return f\"Unresolvable hints: {e}\"\n    for name, hint in hints.items():\n        if name == \"return\":\n            continue\n        if str(hint).startswith(\"typing.Callable\"):\n            return f\"Parameter '{name}' is Callable - not JSON schema-able\"\n    return None","typeGuard":"def schema_safe_annotations(fn) -> bool:\n    try:\n        get_type_hints(fn)\n        return True\n    except Exception:\n        return False","tryCatchPattern":"from haystack.tools.errors import SchemaGenerationError\n\ntry:\n    tool = create_tool_from_function(fn)\nexcept SchemaGenerationError as e:\n    logger.error(\"Cannot schema fn=%s: %s\", fn.__name__, e.__cause__)\n    tool = None","preventionTips":["Use only JSON-serializable types in tool function signatures","Resolve all forward references before tool creation","Wrap tool creation in a smoke test at import/startup time"],"tags":["pydantic","json-schema","tool-definition"],"backgroundTag":"schema-generation-failed","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}