authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-10-03 22:40:57-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-03 22:40:57-07:00
loga92c43b80ba307f112e0ae03bf64d841475cf326
treec4b7f5f6cc87315a9b264f7d00724d6c642657f6
parentbf5c146be914c9b596cdc45d343228271115c099
signature Signed by PGP key B5690EEEBB952194

fix(client-runtime): relay disconnects no longer show as thread errors (#15470)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

2 files changed, 25 insertions(+), 3 deletions(-)

packages/client-runtime/src/errors/transport.test.ts+15
......@@ -1,5 +1,6 @@
11import { describe, expect, it } from "vite-plus/test";
22
3import { NETWORK_BLOCKING_HINT } from "./network.ts";
34import { isTransportConnectionErrorMessage, sanitizeThreadErrorMessage } from "./transport.ts";
45
56describe("isTransportConnectionErrorMessage", () => {
......@@ -30,6 +31,20 @@ describe("isTransportConnectionErrorMessage", () => {
3031 expect(isTransportConnectionErrorMessage("ClientProtocolError: socket closed")).toBe(true);
3132 });
3233
34 it("recognizes relay connection errors that carry the network hint", () => {
35 for (const sentence of [
36 "Relay environment disconnected.",
37 "Relay environment could not establish a WebSocket connection.",
38 ]) {
39 expect(isTransportConnectionErrorMessage(`${sentence} ${NETWORK_BLOCKING_HINT}`)).toBe(true);
40 }
41 expect(
42 isTransportConnectionErrorMessage(
43 "Your ChatGPT connection expired or was disconnected. Sign in again.",
44 ),
45 ).toBe(false);
46 });
47
3348 it("returns true for the T3 server WebSocket message", () => {
3449 expect(isTransportConnectionErrorMessage("Unable to connect to the T3 server WebSocket.")).toBe(
3550 true,
packages/client-runtime/src/errors/transport.ts+10-3
......@@ -1,11 +1,18 @@
1import { NETWORK_BLOCKING_HINT } from "./network.ts";
2
3const escapeRegExp = (text: string) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4
15const TRANSPORT_ERROR_PATTERNS = [
26 /\bSocketCloseError\b/i,
37 /\bSocketOpenError\b/i,
48 /\bSocket is not connected\b/i,
59 /Unable to connect to the T3 server WebSocket\./i,
6 /\bis not connected\.$/i,
7 /\bdisconnected\.$/i,
8 /\bcould not establish a WebSocket connection\.$/i,
10 // The RPC session appends the network hint for relay connections. Any other
11 // trailing text means a different error that the user should still see.
12 new RegExp(
13 `\\b(?:is not connected|disconnected|could not establish a WebSocket connection)\\.(?: ${escapeRegExp(NETWORK_BLOCKING_HINT)})?$`,
14 "i",
15 ),
916 /\bClientProtocolError\b/i,
1017 /\bRpcClientError\b/i,
1118 /\bping timeout\b/i,