{"record":{"id":"2de99f20cf6efde6","repo":"huggingface/smolagents","slug":"cannot-assign-to-name-target-id-doing-this-wo","errorCode":null,"errorMessage":"Cannot assign to name '{target.id}': doing this would erase the existing tool!","messagePattern":"Cannot assign to name '(.+?)': doing this would erase the existing tool!","errorType":"error_code","errorClass":"InterpreterError","httpStatus":null,"severity":"error","filePath":"src/smolagents/local_python_executor.py","lineNumber":804,"sourceCode":"            else:\n                expanded_values.append(result)\n\n        for tgt, val in zip(assign.targets, expanded_values):\n            set_value(tgt, val, state, static_tools, custom_tools, authorized_imports)\n    return result\n\n\ndef set_value(\n    target: ast.AST,\n    value: Any,\n    state: dict[str, Any],\n    static_tools: dict[str, Callable],\n    custom_tools: dict[str, Callable],\n    authorized_imports: list[str],\n) -> None:\n    if isinstance(target, ast.Name):\n        if target.id in static_tools:\n            raise InterpreterError(f\"Cannot assign to name '{target.id}': doing this would erase the existing tool!\")\n        state[target.id] = value\n    elif isinstance(target, ast.Tuple):\n        if not isinstance(value, tuple):\n            if hasattr(value, \"__iter__\") and not isinstance(value, (str, bytes)):\n                value = tuple(value)\n            else:\n                raise InterpreterError(\"Cannot unpack non-tuple value\")\n        if len(target.elts) != len(value):\n            raise InterpreterError(\"Cannot unpack tuple of wrong size\")\n        for i, elem in enumerate(target.elts):\n            set_value(elem, value[i], state, static_tools, custom_tools, authorized_imports)\n    elif isinstance(target, ast.Subscript):\n        obj = evaluate_ast(target.value, state, static_tools, custom_tools, authorized_imports)\n        key = evaluate_ast(target.slice, state, static_tools, custom_tools, authorized_imports)\n        obj[key] = value\n    elif isinstance(target, ast.Attribute):\n        obj = evaluate_ast(target.value, state, static_tools, custom_tools, authorized_imports)\n        setattr(obj, target.attr, value)","sourceCodeStart":786,"sourceCodeEnd":822,"githubUrl":"https://github.com/huggingface/smolagents/blob/30bb1161095dbae2271e6bc3cc4c219cc3897a57/src/smolagents/local_python_executor.py#L786-L822","documentation":"set_value refuses ast.Name assignments whose id collides with a key in static_tools: overwriting would shadow/remove a registered tool for the rest of the execution. The executor raises InterpreterError telling you the assignment would erase the tool.","triggerScenarios":"Executed code assigns to a name that is a static tool: e.g. with a registered tool named 'search', code containing `search = 'foo'`, `search, x = 1, 2`, or a for-loop target/comprehension variable named `search`. The check applies to Assign, AnnAssign, AugAssign targets, for-loops and comprehensions.","commonSituations":"LLM picks a generic variable name that matches a tool name ('search', 'final_answer', 'visit_webpage'); tuple unpacking or iteration reuses a tool name; user names their custom tool something common like 'read' or 'get'.","solutions":["Rename the variable in the generated code to something non-colliding (e.g. search_result instead of search)","Rename the custom tool to a less generic name when registering it","Prompt the agent with the list of reserved tool names and instruct it to avoid them as identifiers"],"exampleFix":"# before\ncode = \"search = 'query text'\\nfinal_answer(search)\"\n\n# after\ncode = \"search_query = 'query text'\\nfinal_answer(search_query)\"","handlingStrategy":"validation","validationCode":"import ast\nreserved = set(static_tools)  # e.g. {'search', 'final_answer'}\nfor node in ast.walk(ast.parse(code)):\n    names = set()\n    if isinstance(node, (ast.Assign, ast.AnnAssign, ast.AugAssign)):\n        targets = node.targets if isinstance(node, ast.Assign) else [node.target]\n        names |= {t.id for t in targets if isinstance(t, ast.Name)}\n    if isinstance(node, (ast.For, ast.comprehension)):\n        names |= {n.id for n in ast.walk(node.target) if isinstance(n, ast.Name)}\n    clash = names & reserved\n    if clash:\n        raise ValueError(f'variable names shadow tools: {clash}')","typeGuard":null,"tryCatchPattern":"from smolagents.local_python_executor import InterpreterError\ntry:\n    evaluate_python(code, static_tools=static_tools)\nexcept InterpreterError as e:\n    if 'would erase the existing tool' in str(e):\n        code = rename_shadowed_vars(code, avoid=set(static_tools))\n        evaluate_python(code, static_tools=static_tools)","preventionTips":["Give custom tools distinctive, non-generic names (my_search_tool, not search)","Tell the agent which names are reserved before it writes code","Lint generated snippets for assignments colliding with tool names"],"tags":["smolagents","name-collision","static-tools","variable-shadowing","interpreter-error"],"backgroundTag":"identifier-name-collision","analyzedSha":"30bb1161095dbae2271e6bc3cc4c219cc3897a57","analyzedAt":"2026-08-28T18:52:54.169Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}