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

  1. Move conditional/loop logic out of the class body into __init__ or a classmethod
  2. Replace class-body branching with precomputed values or default arguments
  3. 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

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


AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28). Data as JSON: /api/errors/f177503093f73ec2. Report an issue: GitHub.