Summary
When startTickWatch() detects a tick timeout (gap > tickIntervalMs * 2), it closes the WebSocket but does not flush/reject the pending requests in this.pending. Those requests then hang indefinitely until flushPendingErrors is eventually called.
Root Cause
// startTickWatch(), src/gateway/client.ts
if (gap > this.tickIntervalMs * 2) {
this.ws?.close(4000, "tick timeout");
// pending requests are NOT flushed here
}
flushPendingErrors is called on the close event, but there is a window between the close call and the event firing where new pending entries could accumulate or existing ones remain.
Impact
- Pending requests may not be rejected promptly on tick timeout
- Combined with Bug P1 (no request timeout), this creates a compounding leak
- Adds latency to error propagation during gateway disconnects
Suggested Fix
if (gap > this.tickIntervalMs * 2) {
this.flushPendingErrors(new Error("Tick timeout — gateway unresponsive"));
this.ws?.close(4000, "tick timeout");
}
Environment
Summary
When
startTickWatch()detects a tick timeout (gap > tickIntervalMs * 2), it closes the WebSocket but does not flush/reject the pending requests inthis.pending. Those requests then hang indefinitely untilflushPendingErrorsis eventually called.Root Cause
flushPendingErrorsis called on thecloseevent, but there is a window between the close call and the event firing where new pending entries could accumulate or existing ones remain.Impact
Suggested Fix
Environment