huggingface/smolagents · error · InterpreterError
Unsupported statement in class body: {stmt.__class__.__name_
Error message
Unsupported statement in class body: {stmt.__class__.__name__} What it means
evaluate_class_def only supports a fixed set of statements inside a class body (assignments, AnnAssign, FunctionDef, AsyncFunctionDef, Pass, Expr docstrings); anything else (if, for, while, try, with, Return, etc.) raises InterpreterError naming the statement class. Python itself forbids many of these in class bodies, but the executor is stricter.
Source
Thrown at src/smolagents/local_python_executor.py:614
value = evaluate_ast(stmt.value, state, static_tools, custom_tools, authorized_imports)
for target in stmt.targets:
if isinstance(target, ast.Name):
class_dict[target.id] = value
elif isinstance(target, ast.Attribute):
obj = evaluate_ast(target.value, class_dict, static_tools, custom_tools, authorized_imports)
setattr(obj, target.attr, value)
elif isinstance(stmt, ast.Pass):
pass
elif (
isinstance(stmt, ast.Expr)
and stmt == class_def.body[0]
and isinstance(stmt.value, ast.Constant)
and isinstance(stmt.value.value, str)
):
# Check if it is a docstring: first statement in class body which is a string literal expression
class_dict["__doc__"] = stmt.value.value
else:
raise InterpreterError(f"Unsupported statement in class body: {stmt.__class__.__name__}")
new_class = metaclass(class_name, tuple(bases), class_dict)
state[class_name] = new_class
return new_class
def evaluate_annassign(
annassign: ast.AnnAssign,
state: dict[str, Any],
static_tools: dict[str, Callable],
custom_tools: dict[str, Callable],
authorized_imports: list[str],
) -> Any:
# If there's a value to assign, evaluate it
if annassign.value:
value = evaluate_ast(annassign.value, state, static_tools, custom_tools, authorized_imports)
# Set the value for the target
set_value(annassign.target, value, state, static_tools, custom_tools, authorized_imports)View on GitHub (pinned to 30bb116109)
Solutions
- Move conditional/loop logic out of the class body into __init__ or a classmethod
- Replace class-body branching with precomputed values or default arguments
- Simplify to plain attribute and method definitions inside the class
Example fix
# before code = "class Config:\n if debug:\n level = 'DEBUG'" # after code = "class Config:\n level = 'DEBUG' if debug else 'INFO'"
Defensive patterns
Strategy: validation
Validate before calling
import ast
ALLOWED = (ast.FunctionDef, ast.AsyncFunctionDef, ast.Assign, ast.AnnAssign, ast.Pass)
for node in ast.walk(ast.parse(code)):
if isinstance(node, ast.ClassDef):
for stmt in node.body:
if not isinstance(stmt, ALLOWED) and not (isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Constant)):
raise ValueError(f'statement {type(stmt).__name__} not allowed in class body') Try / catch
from smolagents.local_python_executor import InterpreterError
try:
evaluate_python(code)
except InterpreterError as e:
if 'Unsupported statement in class body' in str(e):
code = move_logic_to_init(code) Prevention
- Put branching/loops inside methods (__init__), never in the class body
- Use conditional expressions (x = a if c else b) for conditional attributes
- Lint generated code for non-trivial class bodies before execution
When it happens
Trigger: Class body contains an unsupported statement, e.g. `class A:\n if x: y = 1`, a for loop, a with block, or a raise, inside the executed snippet.
Common situations: LLM generates conditional initialization or loops inside a class; metaprogramming-style code pasted into the agent; code that is valid at module level pasted verbatim into a class body.
Related errors
- Forbidden access to module: {result.__name__}
- Forbidden access to module: {result['__name__']}
- Forbidden access to function: {function_name}
- Object is not iterable
- Unsupported AnnAssign target in class body: {type(target).__
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/f177503093f73ec2.
Report an issue: GitHub.