{"record":{"id":"e3adde36e426c821","repo":"huggingface/smolagents","slug":"cannot-unpack-non-tuple-value","errorCode":null,"errorMessage":"Cannot unpack non-tuple value","messagePattern":"Cannot unpack non-tuple value","errorType":"error_code","errorClass":"InterpreterError","httpStatus":null,"severity":"error","filePath":"src/smolagents/local_python_executor.py","lineNumber":811,"sourceCode":"\ndef set_value(\n    target: ast.AST,\n    value: Any,\n    state: dict[str, Any],\n    static_tools: dict[str, Callable],\n    custom_tools: dict[str, Callable],\n    authorized_imports: list[str],\n) -> None:\n    if isinstance(target, ast.Name):\n        if target.id in static_tools:\n            raise InterpreterError(f\"Cannot assign to name '{target.id}': doing this would erase the existing tool!\")\n        state[target.id] = value\n    elif isinstance(target, ast.Tuple):\n        if not isinstance(value, tuple):\n            if hasattr(value, \"__iter__\") and not isinstance(value, (str, bytes)):\n                value = tuple(value)\n            else:\n                raise InterpreterError(\"Cannot unpack non-tuple value\")\n        if len(target.elts) != len(value):\n            raise InterpreterError(\"Cannot unpack tuple of wrong size\")\n        for i, elem in enumerate(target.elts):\n            set_value(elem, value[i], state, static_tools, custom_tools, authorized_imports)\n    elif isinstance(target, ast.Subscript):\n        obj = evaluate_ast(target.value, state, static_tools, custom_tools, authorized_imports)\n        key = evaluate_ast(target.slice, state, static_tools, custom_tools, authorized_imports)\n        obj[key] = value\n    elif isinstance(target, ast.Attribute):\n        obj = evaluate_ast(target.value, state, static_tools, custom_tools, authorized_imports)\n        setattr(obj, target.attr, value)\n\n\ndef evaluate_call(\n    call: ast.Call,\n    state: dict[str, Any],\n    static_tools: dict[str, Callable],\n    custom_tools: dict[str, Callable],","sourceCodeStart":793,"sourceCodeEnd":829,"githubUrl":"https://github.com/huggingface/smolagents/blob/30bb1161095dbae2271e6bc3cc4c219cc3897a57/src/smolagents/local_python_executor.py#L793-L829","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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"],"exampleFix":"# before\ncode = \"a, b = '12'\"\n\n# after\ncode = \"a, b = (1, 2)\"","handlingStrategy":"type-guard","validationCode":"def can_unpack(v, n) -> bool:\n    return isinstance(v, tuple) and len(v) == n or (hasattr(v, '__iter__') and not isinstance(v, (str, bytes)) and len(list(v)) == n)","typeGuard":"def is_unpackable(v) -> bool:\n    return isinstance(v, tuple) or (hasattr(v, '__iter__') and not isinstance(v, (str, bytes)))","tryCatchPattern":"from smolagents.local_python_executor import InterpreterError\ntry:\n    evaluate_python(code)\nexcept InterpreterError as e:\n    if 'Cannot unpack non-tuple value' in str(e):\n        code = guard_unpack_sites(code)  # add isinstance checks before a, b = v","preventionTips":["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"],"tags":["smolagents","unpacking","type-error","interpreter-error","sandbox"],"backgroundTag":"unpacking-type-mismatch","analyzedSha":"30bb1161095dbae2271e6bc3cc4c219cc3897a57","analyzedAt":"2026-08-28T18:52:54.169Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}