Skip to content

Commit 5cb7014

Browse files
authored
fix: remap grpc "client error (Connect)" to UnavailableError for reconnection (#458)
grpc-js reports transport-level connection failures on streaming RPCs as StatusCode.Unknown instead of StatusCode.Unavailable. This prevents the client from tearing down the dead channel and triggering cluster rediscovery when the connected node goes down. The fix remaps errors containing "client error (Connect)" to UnavailableError in convertToCommandError, consistent with the existing "write after end" workaround. This ensures shouldReconnect returns true, the channel is torn down, and discovery finds the new leader.
1 parent 2da4ec9 commit 5cb7014

File tree

2 files changed

+10
-4
lines changed

2 files changed

+10
-4
lines changed

packages/db-client/src/utils/CommandError.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,13 @@ export const convertToCommandError = (error: Error): CommandError | Error => {
714714
return new UnavailableError(error);
715715
}
716716

717+
// grpc-js reports transport-level connection failures on streaming RPCs as
718+
// StatusCode.Unknown instead of StatusCode.Unavailable. This prevents the
719+
// client from tearing down the dead channel and triggering rediscovery.
720+
if (error.details.includes("client error (Connect)")) {
721+
return new UnavailableError(error);
722+
}
723+
717724
return new UnknownError(error);
718725
};
719726

packages/test/src/connection/reconnect/all-nodes-down.test.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ describe.skip("reconnect", () => {
9494
})) {
9595
count++;
9696
}
97-
}).rejects.toThrowErrorMatchingInlineSnapshot(
98-
`"UnknownError("Server-side error: status: Unknown, message: \\"client error (Connect)\\", details: [], metadata: MetadataMap { headers: {} }")"`
99-
);
97+
}).rejects.toThrowError(UnavailableError);
10098
// create subsctiption
10199
await expect(
102100
client.createPersistentSubscriptionToStream(
@@ -127,6 +125,7 @@ describe.skip("reconnect", () => {
127125
'"Failed to discover after 10 attempts."'
128126
);
129127
// read the stream
128+
// Channel is torn down by now, so readStream goes through discovery which fails.
130129
await expect(async () => {
131130
let count = 0;
132131
for await (const e of client.readStream(STREAM_NAME, {
@@ -135,7 +134,7 @@ describe.skip("reconnect", () => {
135134
count++;
136135
}
137136
}).rejects.toThrowErrorMatchingInlineSnapshot(
138-
`"UnknownError("Server-side error: status: Unknown, message: \\"client error (Connect)\\", details: [], metadata: MetadataMap { headers: {} }")"`
137+
'"Failed to discover after 10 attempts."'
139138
);
140139
// create subsctiption
141140
await expect(

0 commit comments

Comments
 (0)