huggingface/smolagents · error · InterpreterError

Object {obj} has no attribute {func_name}

Error message

Object {obj} has no attribute {func_name}

What it means

For method-style calls (obj.method(...)), evaluate_call resolves the object then checks hasattr(obj, func_name) and raises InterpreterError naming the object and missing attribute — mirroring AttributeError inside the sandbox, with the object's repr embedded in the message (which can be noisy for large objects).

Source

Thrown at src/smolagents/local_python_executor.py:845

    state: dict[str, Any],
    static_tools: dict[str, Callable],
    custom_tools: dict[str, Callable],
    authorized_imports: list[str],
) -> Any:
    if not isinstance(call.func, (ast.Call, ast.Lambda, ast.Attribute, ast.Name, ast.Subscript)):
        raise InterpreterError(f"This is not a correct function: {call.func}).")

    func, func_name = None, None

    if isinstance(call.func, ast.Call):
        func = evaluate_ast(call.func, state, static_tools, custom_tools, authorized_imports)
    elif isinstance(call.func, ast.Lambda):
        func = evaluate_ast(call.func, state, static_tools, custom_tools, authorized_imports)
    elif isinstance(call.func, ast.Attribute):
        obj = evaluate_ast(call.func.value, state, static_tools, custom_tools, authorized_imports)
        func_name = call.func.attr
        if not hasattr(obj, func_name):
            raise InterpreterError(f"Object {obj} has no attribute {func_name}")
        func = getattr(obj, func_name)
    elif isinstance(call.func, ast.Name):
        func_name = call.func.id
        if func_name in state:
            func = state[func_name]
        elif func_name in static_tools:
            func = static_tools[func_name]
        elif func_name in custom_tools:
            func = custom_tools[func_name]
        elif func_name in ERRORS:
            func = ERRORS[func_name]
        else:
            raise InterpreterError(
                f"Forbidden function evaluation: '{call.func.id}' is not among the explicitly allowed tools or defined/imported in the preceding code"
            )
    elif isinstance(call.func, ast.Subscript):
        func = evaluate_ast(call.func, state, static_tools, custom_tools, authorized_imports)
        if not callable(func):

View on GitHub (pinned to 30bb116109)

Solutions

  1. Guard before calling: `if x is not None and hasattr(x, 'append'): x.append(1)`
  2. Verify the actual type with type(x) or isinstance and adapt the call
  3. Fix the method name / use the correct API for the type (e.g. json.dumps instead of .json on a dict)

Example fix

# before
code = "final_answer(result.strip())"  # result may be None

# after
code = "final_answer(result.strip() if result else '')"
Defensive patterns

Strategy: type-guard

Validate before calling

def has_method(obj, name: str) -> bool:
    return obj is not None and hasattr(obj, name) and callable(getattr(obj, name))

Type guard

def has_method(obj, name: str) -> bool:
    return obj is not None and callable(getattr(obj, name, None))

Try / catch

from smolagents.local_python_executor import InterpreterError
try:
    evaluate_python(code)
except InterpreterError as e:
    if 'has no attribute' in str(e):
        code = add_none_guard(code)  # e.g. result.strip() -> result.strip() if result else ''

Prevention

When it happens

Trigger: Executed code calls a method that doesn't exist on the receiver: `x.append(1)` when x is an int, `df.col_name()` typo, calling `.json()` on a plain dict, or calling a method on None (e.g. result is None and code does result.strip()).

Common situations: Tool returns None on failure and the model chains a method call on it; wrong type assumption (str vs list); pandas/numpy API mix-ups; version differences where a method was renamed/removed in a library the code imports.

Related errors


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