huggingface/smolagents · error · InterpreterError
Cannot unpack non-tuple value
Error message
Cannot unpack non-tuple value
What it means
When unpacking into a tuple target (a, b = value), set_value requires value to be a tuple; iterables that are not str/bytes get converted, but non-iterables raise InterpreterError('Cannot unpack non-tuple value'). Strings and bytes are deliberately rejected to avoid surprising per-character unpacking.
Source
Thrown at src/smolagents/local_python_executor.py:811
def set_value(
target: ast.AST,
value: Any,
state: dict[str, Any],
static_tools: dict[str, Callable],
custom_tools: dict[str, Callable],
authorized_imports: list[str],
) -> None:
if isinstance(target, ast.Name):
if target.id in static_tools:
raise InterpreterError(f"Cannot assign to name '{target.id}': doing this would erase the existing tool!")
state[target.id] = value
elif isinstance(target, ast.Tuple):
if not isinstance(value, tuple):
if hasattr(value, "__iter__") and not isinstance(value, (str, bytes)):
value = tuple(value)
else:
raise InterpreterError("Cannot unpack non-tuple value")
if len(target.elts) != len(value):
raise InterpreterError("Cannot unpack tuple of wrong size")
for i, elem in enumerate(target.elts):
set_value(elem, value[i], state, static_tools, custom_tools, authorized_imports)
elif isinstance(target, ast.Subscript):
obj = evaluate_ast(target.value, state, static_tools, custom_tools, authorized_imports)
key = evaluate_ast(target.slice, state, static_tools, custom_tools, authorized_imports)
obj[key] = value
elif isinstance(target, ast.Attribute):
obj = evaluate_ast(target.value, state, static_tools, custom_tools, authorized_imports)
setattr(obj, target.attr, value)
def evaluate_call(
call: ast.Call,
state: dict[str, Any],
static_tools: dict[str, Callable],
custom_tools: dict[str, Callable],View on GitHub (pinned to 30bb116109)
Solutions
- Check/guard the shape before unpacking: `if isinstance(v, (tuple, list)) and len(v) == 2: a, b = v`
- Convert first: `a, b = tuple(v)` or `a, b = list(v)` when v is a non-str iterable
- Fix the data source so it genuinely returns the expected tuple
Example fix
# before code = "a, b = '12'" # after code = "a, b = (1, 2)"
Defensive patterns
Strategy: type-guard
Validate before calling
def can_unpack(v, n) -> bool:
return isinstance(v, tuple) and len(v) == n or (hasattr(v, '__iter__') and not isinstance(v, (str, bytes)) and len(list(v)) == n) Type guard
def is_unpackable(v) -> bool:
return isinstance(v, tuple) or (hasattr(v, '__iter__') and not isinstance(v, (str, bytes))) Try / catch
from smolagents.local_python_executor import InterpreterError
try:
evaluate_python(code)
except InterpreterError as e:
if 'Cannot unpack non-tuple value' in str(e):
code = guard_unpack_sites(code) # add isinstance checks before a, b = v Prevention
- Never unpack strings/bytes or scalars; convert explicitly first
- Guard tool results: if not isinstance(r, (list, tuple)): r = [r]
- Prefer indexing (v[0], v[1]) when the shape is uncertain
When it happens
Trigger: `a, b = 5`, `a, b = None`, `a, b = 'xy'`, or unpacking an object with no __iter__ in executed code; also fires for for-loop targets and comprehension unpacking since they share set_value.
Common situations: Tool returns None or a scalar where the model expected a pair; unpacking a string the model assumed was a tuple; unpacking a dict yields keys confusion; LLM pattern-matches tuple syntax onto non-tuple data.
Related errors
- Object is not iterable
- Cannot unpack tuple of wrong size
- Forbidden access to module: {result.__name__}
- Forbidden access to module: {result['__name__']}
- Forbidden access to function: {function_name}
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/e3adde36e426c821.
Report an issue: GitHub.