{"record":{"id":"cdf8c54c05b9e2b6","repo":"run-llama/llama_index","slug":"tool-name-must-be-set","errorCode":null,"errorMessage":"Tool name must be set","messagePattern":"Tool name must be set","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/objects/tool_node_mapping.py","lineNumber":143,"sourceCode":"    \"\"\"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.\"\"\"\n        if node.metadata is None:\n            raise ValueError(\"Metadata must be set\")\n        return self._tools[node.metadata[\"name\"]]\n","sourceCodeStart":125,"sourceCodeEnd":155,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/objects/tool_node_mapping.py#L125-L155","documentation":"SimpleQueryToolNodeMapping._add_object requires tool.metadata.name to be a non-None string because the name is the dict key mapping node back to tool. QueryEngineTool metadata can end up with name=None when constructed with a partial/empty ToolMetadata, and adding it raises ValueError('Tool name must be set'). Note this triggers on add (from_objects), not at tool construction.","triggerScenarios":"SimpleQueryToolNodeMapping.from_objects([tool]) or obj_index.add_object(tool) where tool was built with ToolMetadata(description=...) only, or QueryEngineTool.from_defaults called without metadata/name so a default None leaked through.","commonSituations":"Creating QueryEngineTool with only a description; programmatic tool generation where the name field was forgotten; older llama-index versions allowing None names more permissively.","solutions":["Always pass an explicit name: ToolMetadata(name=\"my_index\", description=\"...\")","Validate before adding: `if not tool.metadata.name: raise ...` in your tool factory","Generate deterministic names programmatically (e.g. from the index identifier) when building many tools in a loop"],"exampleFix":"# before\ntool = QueryEngineTool.from_defaults(query_engine=qe, metadata=ToolMetadata(description=\"city facts\"))\nmapping = SimpleQueryToolNodeMapping.from_objects([tool])  # ValueError: Tool name must be set\n\n# after\ntool = QueryEngineTool.from_defaults(query_engine=qe, metadata=ToolMetadata(name=\"city_facts\", description=\"city facts\"))\nmapping = SimpleQueryToolNodeMapping.from_objects([tool])","handlingStrategy":"validation","validationCode":"for tool in tools:\n    if not getattr(tool.metadata, \"name\", None):\n        raise ValueError(f\"tool has no name: {tool!r}; set ToolMetadata(name=...)\")\nmapping = SimpleQueryToolNodeMapping.from_objects(tools)","typeGuard":"def tool_has_name(tool) -> bool:\n    return bool(getattr(getattr(tool, \"metadata\", None), \"name\", None))","tryCatchPattern":"try:\n    mapping.add_object(tool)  # or from_objects\nexcept ValueError as e:\n    if \"Tool name must be set\" in str(e):\n        tool.metadata.name = generated_unique_name(tool)\n        mapping.add_object(tool)\n    else:\n        raise","preventionTips":["Always construct ToolMetadata(name=..., description=...) together","In tool factories, assert the name is a non-empty string before returning"],"tags":["tools","query-engine","validation","metadata"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}