deepset-ai/haystack · error · SchemaGenerationError

Failed to create JSON schema for function '{function.__name_

Error message

Failed to create JSON schema for function '{function.__name__}'

What it means

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

Source

Thrown at haystack/tools/from_function.py:170

        # Skip Callable types since Pydantic cannot generate JSON schemas for them
        if _contains_callable_type(param.annotation):
            continue

        # if the parameter has not a default value, Pydantic requires an Ellipsis (...)
        # to explicitly indicate that the parameter is required
        default = param.default if param.default is not param.empty else ...
        fields[param_name] = (param.annotation, default)

        if hasattr(param.annotation, "__metadata__"):
            descriptions[param_name] = param.annotation.__metadata__[0]

    # create Pydantic model and generate JSON schema
    try:
        model = create_model(function.__name__, **fields)
        schema = model.model_json_schema()
    except Exception as e:
        raise SchemaGenerationError(f"Failed to create JSON schema for function '{function.__name__}'") from e

    # we don't want to include title keywords in the schema, as they contain redundant information
    # there is no programmatic way to prevent Pydantic from adding them, so we remove them later
    # see https://github.com/pydantic/pydantic/discussions/8504
    _remove_title_from_schema(schema)

    # add parameters descriptions to the schema
    for param_name, param_description in descriptions.items():
        if param_name in schema["properties"]:
            schema["properties"][param_name]["description"] = param_description

    is_async = inspect.iscoroutinefunction(function)

    return Tool(
        name=name or function.__name__,
        description=tool_description,
        parameters=schema,
        function=None if is_async else function,

View on GitHub (pinned to e318778c9b)

Solutions

  1. Check the chained __cause__ exception to identify the failing parameter type
  2. Replace unsupported annotations (Callable, custom classes) with JSON-serializable types (str, int, float, bool, list, dict, Enum, BaseModel)
  3. Ensure any forward references resolve at call time (import the types before tool creation)
  4. Fix generic annotations, e.g. use list[str] instead of a partially parameterized or erroneous generic

Example fix

// before
def run_query(db: Connection, cb: Callable) -> dict:
    ...

// after
def run_query(query: str) -> dict:
    ...
Defensive patterns

Strategy: try-catch

Validate before calling

from typing import get_type_hints

def validate_schemaable(fn) -> str | None:
    try:
        hints = get_type_hints(fn)
    except Exception as e:
        return f"Unresolvable hints: {e}"
    for name, hint in hints.items():
        if name == "return":
            continue
        if str(hint).startswith("typing.Callable"):
            return f"Parameter '{name}' is Callable - not JSON schema-able"
    return None

Type guard

def schema_safe_annotations(fn) -> bool:
    try:
        get_type_hints(fn)
        return True
    except Exception:
        return False

Try / catch

from haystack.tools.errors import SchemaGenerationError

try:
    tool = create_tool_from_function(fn)
except SchemaGenerationError as e:
    logger.error("Cannot schema fn=%s: %s", fn.__name__, e.__cause__)
    tool = None

Prevention

When it happens

Trigger: @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.

Common situations: 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.

Related errors


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