Skip to content

[bug] A CODING_SESSION run that dies logs nothing — 0 logError calls where every peer workflow has 3-5, so a failed run exists only as a chat bubble #529

Description

@serge-ivo

A CODING_SESSION run that dies leaves no durable record anywhere but a chat bubble

$ grep -c logError workers/api/src/workflows/coding-session.ts
0

Every peer workflow logs its own crash:

workflow logError calls
job-apply.ts 4
browser-task.ts 4
pipeline-run.ts 5
agent-loop.ts 3
coding-session.ts 0

Measured on a real failure

Instance f8ddc272-0390-4826-8812-94989e3d2ebd, run died 2026-08-12 07:18:48Z:

surface newest record
instance_messages "Loop stopped (failed) — run error: UserAiProviderError: The AI provider stopped sending mid-reply…"
list_errors ❌ newest row for this instance is 07:07:10
agent_trace (all levels, 200 rows) ❌ newest event is 07:14:34
instance_board ❌ no card

The board is empty by design on this path: cards are minted only for delegations (coding-session.ts:231, if (event.payload.boardTaskId)), and a chat-initiated start_work passes none. That is defensible on its own; combined with no error log it means the only record of a failed autonomous run is a chat message the owner has to scroll to.

Why this is more than tidiness

It made a real question unanswerable. 2bc9475 (#518) added an automatic retry for a failed chat turn, gated on the provider's own retryable verdict (lib/resumable-round.ts:163-167). The 07:18:48 failure was a Pilot run, not a chat turn, and the natural next question — did the retry path apply here, and if not should it — cannot be answered, because the workflow recorded nothing to inspect.

It also could not be established whether that failure was a genuine provider stall or the owner's Anthropic credit exhaustion (two Anthropic (400): Your credit balance is too low errors at 06:59:50 and 07:07:09) resurfacing on the Pilot's streaming path. Those are different problems with different fixes, and the run left nothing to tell them apart.

Adjacent, and distinct

#527 asks for an MCP reader over coding_timeline — that is about auditing a finished run. This is about a failed run producing no error record at all. Fixing #527 would not surface this failure, because the timeline is not where a crash is recorded on the peer workflows either.

Acceptance criteria

  1. A CODING_SESSION run that throws writes a durable error record, the way job-apply, browser-task, pipeline-run and agent-loop already do — readable via list_errors / agent_trace without scrolling chat.
  2. The record distinguishes the failure class where the platform knows it: a provider stall, a credentials/credit failure, and a platform ceiling (see A 2-hour run that closed ten issues and pushed 15 times is reported as "outcome: failed" with a Wrangler docs link — the Cloudflare subrequest ceiling is relayed raw as the objective failing #523) are three different things and currently read identically.
  3. It carries enough to correlate — run id, session id, trace id — so a failed run can be joined to the turn that started it.
  4. A test asserting the write on the throw path, not merely on the happy path.
  5. Consider whether a failed chat-initiated start_work should mint a board card too, or state why the chat message is the right and only owner-facing surface.

Verified vs inferred

  • Verified: the grep counts, all four surface queries above with their timestamps, coding-session.ts:231's board-card condition, and resumable-round.ts:163-167.
  • Inferred: nothing load-bearing. The claim is an absence, and the absence was grepped.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions