{"record":{"id":"eb6aeb34e6dfaf59","repo":"deepset-ai/haystack","slug":"failed-to-create-json-schema-for-the-run-method-of","errorCode":null,"errorMessage":"Failed to create JSON schema for the run method of Component '{component.__class__.__name__}'","messagePattern":"Failed to create JSON schema for the run method of Component '(.+?)'","errorType":"exception","errorClass":"SchemaGenerationError","httpStatus":null,"severity":"error","filePath":"haystack/tools/component_tool.py","lineNumber":368,"sourceCode":"            if _unwrap_optional(input_type) is State:\n                continue\n\n            description = param_descriptions.get(input_name, f\"Input '{input_name}' for the component.\")\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 = ... if socket.is_mandatory else socket.default_value\n            resolved_type = _resolve_type(input_type)\n            fields[input_name] = (resolved_type, Field(default=default, description=description))\n\n        parameters_schema: dict[str, Any] = {}\n        try:\n            # No `__doc__`: it would surface as a top-level `description` on the parameters schema,\n            # which LLM providers ignore. The component description feeds the tool-level description.\n            model = create_model(component.run.__name__, **fields)\n            parameters_schema = model.model_json_schema()\n        except Exception as e:\n            raise SchemaGenerationError(\n                f\"Failed to create JSON schema for the run method of Component '{component.__class__.__name__}'\"\n            ) 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(parameters_schema)\n\n        return parameters_schema\n\n    def _convert_param(self, param_value: Any, param_type: type) -> Any:\n        \"\"\"\n        Converts a single parameter value to the expected type.\n\n        :param param_value: The value to convert.\n        :param param_type: The expected type of the parameter.\n\n        :returns:","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/tools/component_tool.py#L350-L386","documentation":"Raised by ComponentTool._create_tool_parameters_schema when Pydantic fails to build a JSON schema from the component's run() method signature. ComponentTool wraps a Haystack Component so it can be exposed as a Tool; to do that it introspects run()'s parameters with type hints and calls create_model(...).model_json_schema(). If any parameter annotation cannot be converted to a JSON schema (unsupported types, broken generics, forward references that don't resolve), the underlying exception is chained and re-raised as SchemaGenerationError.","triggerScenarios":"ComponentTool(component=SomeComponent()) where the component's run() method has a parameter type hint that Pydantic cannot model, e.g. an unresolvable forward reference, a Callable without parameters, arbitrary classes, or a badly parameterized generic.","commonSituations":"Writing a custom component whose run() takes non-serializable objects (DB connections, clients, callables); renaming/moving types so string annotations no longer resolve; Python version changes altering typing semantics.","solutions":["Inspect the chained exception (__cause__) to find which run() parameter failed schema generation","Change the offending run() parameter type hint to a JSON-serializable Pydantic-compatible type (str, int, list, dict, BaseModel)","Remove or replace unsupported annotations like plain Callable, custom non-serializable classes, or unresolved forward references","Provide a static 'parameters' schema via Tool instead of letting ComponentTool derive it from run()"],"exampleFix":"// before\nclass MyComponent:\n    def run(self, client: SomeClient) -> dict:\n        ...\n\n// after\nclass MyComponent:\n    def run(self, endpoint: str) -> dict:\n        ...","handlingStrategy":"validation","validationCode":"import inspect\nfrom typing import get_type_hints\n\ndef validate_component_run_schema(component) -> str | None:\n    try:\n        hints = get_type_hints(component.run)\n    except Exception as e:\n        return f\"Unresolvable type hints on run(): {e}\"\n    for name, hint in hints.items():\n        if name == \"return\":\n            continue\n        if not hasattr(hint, \"__origin__\") and hint in (object, type(None)):\n            return f\"Parameter '{name}' has non-serializable hint {hint}\"\n    return None\n\nproblem = validate_component_run_schema(my_component)\nassert problem is None, problem","typeGuard":"def has_annotated_run(component) -> bool:\n    params = inspect.signature(component.run).parameters\n    return all(p.annotation is not inspect.Parameter.empty for p in params.values())","tryCatchPattern":"from haystack.tools.errors import SchemaGenerationError\n\ntry:\n    tool = ComponentTool(component=my_component)\nexcept SchemaGenerationError as e:\n    logger.error(\"run() signature not schema-able: %s\", e.__cause__)\n    raise","preventionTips":["Annotate every run() parameter with a JSON-serializable Pydantic-supported type","Avoid Callable, client objects, and unresolved forward references in run() signatures","Unit-test ComponentTool construction for each custom component"],"tags":["pydantic","json-schema","tool-definition","component"],"backgroundTag":"schema-generation-failed","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}