From 268ee4288dd9c94974d87ed1d12f065a76506842 Mon Sep 17 00:00:00 2001 From: iceteaSA <171169159+iceteaSA@users.noreply.github.com> Date: Sun, 17 May 2026 11:38:51 +0200 Subject: [PATCH] fix(relay): handle WS errors during optimistic response streaming When an optimistic response is already streaming (responseStartedAt is set), the pending promise was already resolved. Calling failPending() would reject a settled promise and leave the ReadableStream hanging with no more data and no close signal. Now injects an SSE error event into the stream and closes the socket cleanly, matching the existing upstream-4xx handling in response_start. --- packages/core/src/relay.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/core/src/relay.ts b/packages/core/src/relay.ts index 9dc7376..a577052 100644 --- a/packages/core/src/relay.ts +++ b/packages/core/src/relay.ts @@ -808,6 +808,23 @@ class PersistentRelaySession { return } if (message.type === 'error') { + // If an optimistic response is already streaming (responseStartedAt is + // set), the pending promise was already resolved — calling failPending + // would reject a settled promise and leave the stream hanging. Instead, + // inject an SSE error event and close cleanly. + if (pending.optimisticResponse && pending.responseStartedAt != null) { + relayLog( + `websocket relay error during optimistic response session=${shortAffinity(this.affinity)} request=${pending.payload.id} status=${message.status} message=${message.message || 'unknown'}`, + ) + pending.streamController?.enqueue( + new TextEncoder().encode( + `event: error\ndata: ${JSON.stringify({ type: 'error', error: { type: 'relay_error', message: message.message || 'relay error' } })}\n\n`, + ), + ) + this.finishPending() + this.socket?.close() + return + } if ( message.status === 409 && this.retryPendingBeforeResponse(