huggingface/smolagents · error · InterpreterError
Forbidden call to dunder function: {func.__name__}
Error message
Forbidden call to dunder function: {func.__name__} What it means
Calls to dunder (double-underscore) methods are forbidden unless the name appears in static_tools or the interpreter's ALLOWED_DUNDER_METHODS whitelist. This prevents sandbox escapes via tricks like obj.__class__.__bases__[0].__subclasses__() or .__reduce__().
Source
Thrown at src/smolagents/local_python_executor.py:917
return super(cls, instance)
else:
raise InterpreterError("super() takes at most 2 arguments")
elif func_name == "print":
state["_print_outputs"] += " ".join(map(str, args)) + "\n"
return None
else: # Assume it's a callable object
if (inspect.getmodule(func) == builtins) and inspect.isbuiltin(func) and (func not in static_tools.values()):
raise InterpreterError(
f"Invoking a builtin function that has not been explicitly added as a tool is not allowed ({func_name})."
)
if (
hasattr(func, "__name__")
and func.__name__.startswith("__")
and func.__name__.endswith("__")
and (func.__name__ not in static_tools)
and (func.__name__ not in ALLOWED_DUNDER_METHODS)
):
raise InterpreterError(f"Forbidden call to dunder function: {func.__name__}")
return func(*args, **kwargs)
def evaluate_subscript(
subscript: ast.Subscript,
state: dict[str, Any],
static_tools: dict[str, Callable],
custom_tools: dict[str, Callable],
authorized_imports: list[str],
) -> Any:
index = evaluate_ast(subscript.slice, state, static_tools, custom_tools, authorized_imports)
value = evaluate_ast(subscript.value, state, static_tools, custom_tools, authorized_imports)
try:
return value[index]
except (KeyError, IndexError, TypeError) as e:
error_message = f"Could not index {value} with '{index}': {type(e).__name__}: {e}"
if isinstance(index, str) and isinstance(value, Mapping):
close_matches = difflib.get_close_matches(index, list(value.keys()))View on GitHub (pinned to 30bb116109)
Solutions
- Use the equivalent syntactic sugar (len(x), x[0], iter(x)) instead of calling the dunder
- If a dunder legitimately must be callable, add its name to the tools/static_tools you configure
- Avoid introspection chains like __class__/__subclasses__ in generated code
Example fix
# before item = seq.__getitem__(0) # after item = seq[0]
Defensive patterns
Strategy: fallback
Validate before calling
# normalize generated code: replace dunder calls with syntax sugar import re code = re.sub(r'\.__len__\(\)', '', code) code = re.sub(r'(\w+)\.__getitem__\(([^)]+)\)', r'\1[\2]', code)
Try / catch
try:
evaluate_python(code, ...)
except InterpreterError as e:
if 'dunder' in str(e):
# rewrite the offending dunder call to sugar form and retry Prevention
- Use len(x), x[0], iter(x) instead of dunders
- Treat dunder-call attempts in agent output as prompt-injection red flags
- Add only genuinely needed dunders to ALLOWED_DUNDER_METHODS via tools
When it happens
Trigger: Writing an explicit call to a dunder: x.__len__(), obj.__getitem__(0), getattr-style access evaluated to __globals__ or __reduce__, or calling __init__ directly.
Common situations: Agent code or prompt-injected output tries to reach internals for a sandbox escape; using dunder-call style instead of syntax sugar (x[0] instead of x.__getitem__(0)); calling __init__ for manual re-initialization.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Forbidden access to dunder attribute: {expression.attr}
- Invoking a builtin function that has not been explicitly add
- Import of {alias.name} is not allowed. Authorized imports ar
- Import from {expression.module} is not allowed. Authorized i
- Forbidden access to module: {result.__name__}
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/58d4370084d59a54.
Report an issue: GitHub.