Skip to content

worker.ts: ASSIGNMENT_TIMEOUT handler never resolves/rejects pending job promise — worker hangs forever + memory leak #2151

Description

@tsushanth

Bug

In agents/src/worker.ts (around lines 853–862), the ASSIGNMENT_TIMEOUT message handler logs a warning and returns, but never resolves or rejects the PendingAssignment promise that is being awaited on line 859:

```ts
// ASSIGNMENT_TIMEOUT handler (simplified):
case AgentServerMessage_Message.Case.AssignmentTimeout:
logger.warn('assignment timeout');
return; // ← promise never settled

// ...
await this.#pending[req.id]?.promise; // ← hangs forever
```

Two problems result:

  1. Permanent hang: await this.#pending[req.id]?.promise never resolves or rejects after a timeout fires. The worker goroutine for that job is permanently blocked.

  2. Memory leak: The #pending[req.id] entry is only deleted on successful assignment (around line 698). On timeout, it is never cleaned up — each timed-out job leaks one entry from the #pending map for the lifetime of the worker.

Fix

Add a reject (or resolve) slot to the PendingAssignment type and call it in the timeout handler, then delete the entry:

```ts
case AgentServerMessage_Message.Case.AssignmentTimeout: {
const pending = this.#pending[req.id];
if (pending) {
delete this.#pending[req.id];
pending.reject(new Error(assignment timeout for job ${req.id}));
}
return;
}
```

Alternatively, use Promise.race with a timeout-rejection at the await site.

Impact

  • Any job that times out during assignment permanently blocks a worker slot
  • #pending map grows unbounded under sustained timeout conditions
  • Worker process may eventually exhaust memory or become unresponsive

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions