huggingface/smolagents · error · NotImplementedError

Binary operation {type(binop.op).__name__} is not implemente

Error message

Binary operation {type(binop.op).__name__} is not implemented.

What it means

evaluate_binop covers the standard arithmetic/bitwise binary operators; anything else raises NotImplementedError naming the op class (note: NotImplementedError, not InterpreterError). With stock CPython grammar this is defensive — the notable gap historically is MatMult (@) not being implemented, and BoolOp/compare ops go through other paths.

Source

Thrown at src/smolagents/local_python_executor.py:767

        return left_val / right_val
    elif isinstance(binop.op, ast.Mod):
        return left_val % right_val
    elif isinstance(binop.op, ast.Pow):
        return left_val**right_val
    elif isinstance(binop.op, ast.FloorDiv):
        return left_val // right_val
    elif isinstance(binop.op, ast.BitAnd):
        return left_val & right_val
    elif isinstance(binop.op, ast.BitOr):
        return left_val | right_val
    elif isinstance(binop.op, ast.BitXor):
        return left_val ^ right_val
    elif isinstance(binop.op, ast.LShift):
        return left_val << right_val
    elif isinstance(binop.op, ast.RShift):
        return left_val >> right_val
    else:
        raise NotImplementedError(f"Binary operation {type(binop.op).__name__} is not implemented.")


def evaluate_assign(
    assign: ast.Assign,
    state: dict[str, Any],
    static_tools: dict[str, Callable],
    custom_tools: dict[str, Callable],
    authorized_imports: list[str],
) -> Any:
    result = evaluate_ast(assign.value, state, static_tools, custom_tools, authorized_imports)
    if len(assign.targets) == 1:
        target = assign.targets[0]
        set_value(target, result, state, static_tools, custom_tools, authorized_imports)
    else:
        expanded_values = []
        for tgt in assign.targets:
            if isinstance(tgt, ast.Starred):
                expanded_values.extend(result)

View on GitHub (pinned to 30bb116109)

Solutions

  1. Replace `A @ B` with an explicit call: `numpy.matmul(A, B)` or `numpy.dot(A, B)` or `A.dot(B)`
  2. Check the smolagents changelog/upgrade — newer versions may implement MatMult
  3. Keep matrix math in explicitly called library functions rather than operator syntax

Example fix

# before
code = "import numpy as np\nfinal_answer(A @ B)"

# after
code = "import numpy as np\nfinal_answer(np.matmul(A, B))"
Defensive patterns

Strategy: validation

Validate before calling

import ast
for node in ast.walk(ast.parse(code)):
    if isinstance(node, ast.BinOp) and isinstance(node.op, ast.MatMult):
        raise ValueError('A @ B is not supported; use numpy.matmul(A, B) instead')

Try / catch

from smolagents.local_python_executor import evaluate_python
try:
    evaluate_python(code)
except NotImplementedError as e:
    if 'Binary operation' in str(e):
        code = code.replace(' @ ', ' np.matmul(')  # best: rewrite source properly

Prevention

When it happens

Trigger: Executed code uses a binary operator the executor lacks — most commonly the matrix-multiply operator `a @ b` (ast.MatMult) — or an AST is fed with an unhandled operator node.

Common situations: LLM writes numpy code with `A @ B` or `A @ vector`; users port linear-algebra snippets into the sandbox and hit NotImplementedError instead of the expected result.

Related errors


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