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
- 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
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
- 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
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
- Failed to create JSON schema for the run method of Component
- Input must be a dictionary or a list of dictionaries.
- Function '{function.__name__}': parameter '{param_name}' doe
- The 'pipeline' parameter must be an instance of Pipeline. Go
- The provided parameters do not define a valid JSON schema
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/45e53ea12cc2f07d.
Report an issue: GitHub.