huggingface/smolagents · error · InterpreterError
Cannot assign to name '{target.id}': doing this would erase
Error message
Cannot assign to name '{target.id}': doing this would erase the existing tool! What it means
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.
Source
Thrown at src/smolagents/local_python_executor.py:804
else:
expanded_values.append(result)
for tgt, val in zip(assign.targets, expanded_values):
set_value(tgt, val, state, static_tools, custom_tools, authorized_imports)
return result
def set_value(
target: ast.AST,
value: Any,
state: dict[str, Any],
static_tools: dict[str, Callable],
custom_tools: dict[str, Callable],
authorized_imports: list[str],
) -> None:
if isinstance(target, ast.Name):
if target.id in static_tools:
raise InterpreterError(f"Cannot assign to name '{target.id}': doing this would erase the existing tool!")
state[target.id] = value
elif isinstance(target, ast.Tuple):
if not isinstance(value, tuple):
if hasattr(value, "__iter__") and not isinstance(value, (str, bytes)):
value = tuple(value)
else:
raise InterpreterError("Cannot unpack non-tuple value")
if len(target.elts) != len(value):
raise InterpreterError("Cannot unpack tuple of wrong size")
for i, elem in enumerate(target.elts):
set_value(elem, value[i], state, static_tools, custom_tools, authorized_imports)
elif isinstance(target, ast.Subscript):
obj = evaluate_ast(target.value, state, static_tools, custom_tools, authorized_imports)
key = evaluate_ast(target.slice, state, static_tools, custom_tools, authorized_imports)
obj[key] = value
elif isinstance(target, ast.Attribute):
obj = evaluate_ast(target.value, state, static_tools, custom_tools, authorized_imports)
setattr(obj, target.attr, value)View on GitHub (pinned to 30bb116109)
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
Example fix
# before code = "search = 'query text'\nfinal_answer(search)" # after code = "search_query = 'query text'\nfinal_answer(search_query)"
Defensive patterns
Strategy: validation
Validate before calling
import ast
reserved = set(static_tools) # e.g. {'search', 'final_answer'}
for node in ast.walk(ast.parse(code)):
names = set()
if isinstance(node, (ast.Assign, ast.AnnAssign, ast.AugAssign)):
targets = node.targets if isinstance(node, ast.Assign) else [node.target]
names |= {t.id for t in targets if isinstance(t, ast.Name)}
if isinstance(node, (ast.For, ast.comprehension)):
names |= {n.id for n in ast.walk(node.target) if isinstance(n, ast.Name)}
clash = names & reserved
if clash:
raise ValueError(f'variable names shadow tools: {clash}') Try / catch
from smolagents.local_python_executor import InterpreterError
try:
evaluate_python(code, static_tools=static_tools)
except InterpreterError as e:
if 'would erase the existing tool' in str(e):
code = rename_shadowed_vars(code, avoid=set(static_tools))
evaluate_python(code, static_tools=static_tools) Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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'.
Related errors
- Forbidden access to module: {result.__name__}
- Forbidden access to module: {result['__name__']}
- Forbidden access to function: {function_name}
- Object is not iterable
- Unary operation {expression.op.__class__.__name__} is not su
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/2de99f20cf6efde6.
Report an issue: GitHub.