Skip to content

ROADMAP-01 — P0 — Client disconnect leaves zombie "running" rows: CancelledError is unhandled #93

Closed

Description

@getdownandcode

Series: ROADMAP — filed from the 2026-10-27 whole-project assessment · Backlog task: M14-T01 · Priority: P0 · Effort: small

Problem

Agent.run has handlers only for PersistenceError, TimeoutError and Exception. Since Python 3.8 asyncio.CancelledError derives from BaseException, which none of those catch. When an HTTP client disconnects mid-run, Starlette cancels the request task and the cancellation propagates straight through run:

  • _finalize_and_return never runs → the run row stays status='running' in PostgreSQL forever (zombie row)
  • session history is never saved and never gets the _repair_trailing_tool_calls fix applied
  • the in-flight step is invisible in telemetry

The asymmetry is stark: a server-side timeout produces a truthful terminal state (TIMED_OUT), a client-side disconnect produces an orphan. Grep confirms zero references to CancelledError, asyncio.shield or request.is_disconnected in the codebase.

Evidence

  • agentkit/core/agent.py:310–526 — the try block and its three except clauses
  • agentkit/core/agent.py:178 — create_run happens before any finally could persist a terminal state

Suggested fix / acceptance criteria

  • Agent.run catches asyncio.CancelledError, persists a terminal run status (canceled) inside asyncio.shield (so a dying request cannot abort mid-write), then re-raises
  • _repair_trailing_tool_calls runs on the cancellation path so the saved history stays provider-valid
  • Unit test simulates cancellation mid-tool and asserts a terminal status row and a valid history (no running rows)

Suggested branch / commit

fix/cancelled-run-terminal-state · fix(core): persist terminal state on client-disconnect cancellation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions