{"record":{"id":"8b9e05c9a64ec358","repo":"run-llama/llama_index","slug":"object-must-be-of-type-queryenginetool","errorCode":null,"errorMessage":"Object must be of type {QueryEngineTool}","messagePattern":"Object must be of type (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/objects/tool_node_mapping.py","lineNumber":133,"sourceCode":"        raise NotImplementedError(\"Subclasses should implement this!\")\n\n    def persist(\n        self, persist_dir: str = ..., obj_node_mapping_fname: str = ...\n    ) -> None:\n        \"\"\"Persist objs.\"\"\"\n        raise NotImplementedError(\"Subclasses should implement this!\")\n\n\nclass SimpleQueryToolNodeMapping(BaseQueryToolNodeMapping):\n    \"\"\"Simple query tool mapping.\"\"\"\n\n    def __init__(self, objs: Optional[Sequence[QueryEngineTool]] = None) -> None:\n        objs = objs or []\n        self._tools = {tool.metadata.name: tool for tool in objs}\n\n    def validate_object(self, obj: QueryEngineTool) -> None:\n        if not isinstance(obj, QueryEngineTool):\n            raise ValueError(f\"Object must be of type {QueryEngineTool}\")\n\n    @classmethod\n    def from_objects(\n        cls, objs: Sequence[QueryEngineTool], *args: Any, **kwargs: Any\n    ) -> \"BaseObjectNodeMapping\":\n        return cls(objs)\n\n    def _add_object(self, tool: QueryEngineTool) -> None:\n        if tool.metadata.name is None:\n            raise ValueError(\"Tool name must be set\")\n        self._tools[tool.metadata.name] = tool\n\n    def to_node(self, obj: QueryEngineTool) -> TextNode:\n        \"\"\"To node.\"\"\"\n        return convert_tool_to_node(obj)\n\n    def _from_node(self, node: BaseNode) -> QueryEngineTool:\n        \"\"\"From node.\"\"\"","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/objects/tool_node_mapping.py#L115-L151","documentation":"SimpleQueryToolNodeMapping.validate_object enforces that added objects are instances of QueryEngineTool specifically (a BaseTool subclass). Passing a generic BaseTool (e.g. FunctionTool), a plain function, or any other type raises ValueError.","triggerScenarios":"SimpleQueryToolNodeMapping.from_objects(objs) / ObjectIndex.from_objects(objs, SimpleQueryToolNodeMapping) where objs contains FunctionTool, RetrieverTool, or raw callables instead of QueryEngineTool instances.","commonSituations":"Migrating a tool list from an agent (mixed FunctionTool + QueryEngineTool) into one query-tool ObjectIndex; passing retriever tools where query-engine tools are expected; using the wrong Simple*ToolNodeMapping class for the tool type at hand.","solutions":["Use QueryEngineTool.from_defaults(query_engine=..., metadata=ToolMetadata(name=..., description=...)) for every object added to this mapping","Separate mixed tool lists: SimpleToolNodeMapping for BaseTool-family tools, SimpleQueryToolNodeMapping strictly for QueryEngineTool","Convert retrievers first: RetrieverTool is not a QueryEngineTool — wrap retrievers via QueryEngine(retriever) if needed"],"exampleFix":"# before\nobjs = [FunctionTool.from_defaults(fn=search_fn)]  # not a QueryEngineTool\nmapping = SimpleQueryToolNodeMapping.from_objects(objs)  # ValueError\n\n# after\nfrom llama_index.core import QueryEngine\nfrom llama_index.core.tools import QueryEngineTool, ToolMetadata\nqe_tool = QueryEngineTool.from_defaults(query_engine=QueryEngine(retriever), metadata=ToolMetadata(name=\"search\", description=\"search docs\"))\nmapping = SimpleQueryToolNodeMapping.from_objects([qe_tool])","handlingStrategy":"type-guard","validationCode":"from llama_index.core.tools import QueryEngineTool\nbad = [o for o in objs if not isinstance(o, QueryEngineTool)]\nif bad:\n    raise TypeError(f\"non-QueryEngineTool objects: {bad!r}; use SimpleToolNodeMapping for generic tools\")","typeGuard":"from llama_index.core.tools import QueryEngineTool\ndef all_are_query_engine_tools(objs: list) -> bool:\n    return all(isinstance(o, QueryEngineTool) for o in objs)","tryCatchPattern":"try:\n    mapping = SimpleQueryToolNodeMapping.from_objects(objs)\nexcept ValueError as e:\n    if \"must be of type\" in str(e):\n        qe_objs = [o for o in objs if isinstance(o, QueryEngineTool)]\n        mapping = SimpleQueryToolNodeMapping.from_objects(qe_objs)\n    else:\n        raise","preventionTips":["Pick the mapping class by tool type: SimpleQueryToolNodeMapping only for QueryEngineTool","Wrap retrievers/engines with QueryEngineTool.from_defaults before grouping them"],"tags":["tools","query-engine","type-validation","object-index"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}