Skip to content

Fail a task that raises its own TimeoutError under a Timeout - #581

Merged
chrisguidry merged 2 commits into
mainfrom
fix-own-timeouterror
Oct 27, 2026
Merged

chrisguidry merged 2 commits into
mainfrom
fix-own-timeouterror

Conversation

@bunchesofdonald

Copy link
Copy Markdown
Collaborator

The problem. A task with a Timeout dependency that raises TimeoutError from its own body is recorded as a success. Timeout.run waits with asyncio.wait_for(asyncio.shield(task), ...) and catches asyncio.TimeoutError to re-check its deadline. On Python 3.11+ asyncio.TimeoutError is the builtin TimeoutError, so the task's own error lands in that except, the loop sees the task done, and run() returns None. The worker then takes the success path: no ERROR log, no Retry, and success counters count it. Any body that can time out on its own, such as a storage read or an inner asyncio.wait_for, fails silently. On 3.10 the same happens for an inner asyncio.wait_for timeout.

The fix. In that except, if the task is done, return task.result(), which re-raises the task's own exception. The overrun path is unchanged: when the deadline passes the task is still running, so docket still cancels it and raises its own timeout. The same branch also reports the task's real outcome when it finishes on the tick the deadline fires, where the old loop returned None. The loop is now while True, since a finished task always returns.

New tests in tests/test_timeout_task_errors.py cover a body raising TimeoutError (with ValueError as the control), an inner wait_for timeout, Retry being honoured, and the overrun path. The first three fail on main on 3.14, and the inner wait_for test fails on 3.10. The full suite passes at 100% coverage.

Session context

Found when a Perpetual task's object-storage read hit its read timeout and docket logged the run as finished, scheduling the next run a day later. A mutation check showed the first version of the inner wait_for test could not tell the task's error from docket's own overrun on 3.10, so it now checks that the logged exception came from the task body.

🤖 Generated with Claude Code

bunchesofdonald and others added 2 commits October 27, 2026 10:20
Timeout.run catches asyncio.TimeoutError to detect its deadline. On Python
3.11+ that is the builtin TimeoutError, so a TimeoutError from the task body
ended the run as a success, with no ERROR log and no Retry. Now, when the task
has finished, run() returns its result or re-raises its exception.

Found when a Perpetual task's storage read timed out and docket recorded the
run as a success.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The wait_for test now asserts the logged exception came from the task body,
so a substitute TimeoutError raised by Timeout.run fails it on Python 3.10
too. The run loop becomes while True, since a finished task now returns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bunchesofdonald

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-27T15:05:10.478600Z a2cd0e8 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 docket | 🛠️ Build #35445596 | 📁 Comparing a2cd0e8 against latest (698c6c3)

  🔍 Preview build  

1 file changed
± api-reference/index.html

@bunchesofdonald
bunchesofdonald marked this pull request as ready for review October 27, 2026 15:03
@chrisguidry
chrisguidry merged commit a313ccd into main Oct 27, 2026
55 checks passed
@chrisguidry
chrisguidry deleted the fix-own-timeouterror branch October 27, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants