Skip to main content
← Back to list
01Issue
BugShippedSwamp CLIPublic
Assigneeszack

Relationships

#3294 WorkerGateway.dispatch leaks a capacity slot when recording the busy status fails

Opened by zack · 10/12/2026· Shipped 10/13/2026

Found by code reading while triaging #3293; not reproduced at runtime.

Summary

In src/serve/worker_gateway.ts (at dbd7ba9a), WorkerGateway.dispatch pushes the dispatch id into entry.activeDispatchIds and sets the status to busy (lines 466-467), then awaits the set_status transition (lines 468-478) and issues the dispatch credential (line 480). The try/finally that removes the id from activeDispatchIds only starts at line 485.

If the awaited set_status model method rejects (for example a datastore or lock error while writing the worker record), or issueForDispatch throws, dispatch rejects without ever entering the try block. The id stays in activeDispatchIds and the status stays busy for as long as the worker entry lives, so the worker permanently loses one slot (a capacity-1 worker becomes unschedulable) until it re-enrolls or serve restarts.

Expected

A dispatch that fails before it reaches the worker releases its slot, the same as one that fails afterwards.

Suggested direction

Move the push and the busy transition inside the try whose finally filters the id back out, or wrap lines 466-483 in their own cleanup. A unit test in src/serve/worker_gateway_test.ts can use a runModelMethod seam that rejects for set_status busy and assert that workers() reports no active dispatches afterwards.

Relation to #3293

Separate defect. #3293 is about the dispatcher double-counting a healthy running dispatch; this one is a slot that is never returned after a failed transition.

02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 7 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

10/13/2026, 7:32:24 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
zack assigned zack10/13/2026, 6:59:54 PM

Sign in to post a ripple.