Skip to content

Commit 22caa2e

Browse files
committed
fix: Differentiate retry codes for network errors
Splits network error handling: uses 408 for timeouts (timed out, ETIMEDOUT, TLS handshake) and 503 for connection resets (ECONNRESET) to improve retry logic accuracy.
1 parent 04472c0 commit 22caa2e

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

src/nodejs-common/util.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -916,16 +916,29 @@ export class Util {
916916
// This is a conceptual check, the exact error format may vary.
917917
if (
918918
err &&
919-
(err.message?.includes('TLS handshake') ||
920-
err.message?.includes('timed out') ||
921-
err.message?.includes('ETIMEDOUT') ||
922-
err.message?.includes('ECONNRESET'))
919+
(err.message?.toLowerCase().includes('tls handshake') ||
920+
err.message?.toLowerCase().includes('timed out') ||
921+
err.message?.toLowerCase().includes('etimedout') ||
922+
err.message?.toLowerCase().includes('econnreset'))
923923
) {
924+
let code: number;
925+
let message: string;
926+
if (err.message.toLowerCase().includes('econnreset')) {
927+
// ECONNRESET (Connection reset by peer) implies temporary service unavailability
928+
code = 503;
929+
message =
930+
'Connection reset by peer. This suggests the remote service is temporarily unavailable or overloaded.';
931+
} else {
932+
// TLS Handshake, ETIMEDOUT, or generic 'timed out'
933+
// Mapped to 408 (Request Timeout) as a signal for retrying
934+
code = 408;
935+
message =
936+
'Request or TLS handshake timed out. This may be due to CPU starvation or a temporary network issue.';
937+
}
924938
// Create and use your custom error type.
925939
const tlsTimeoutError = new ApiError({
926-
code: 408,
927-
message:
928-
'TLS handshake timeout. This may be due to CPU starvation.',
940+
code,
941+
message,
929942
response: response as r.Response,
930943
});
931944
// Replace the original error with the more descriptive one.

test/nodejs-common/util.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,10 +1209,10 @@ describe('common/util', () => {
12091209

12101210
makeAuthenticatedRequest({} as DecorateRequestOptions, err => {
12111211
assert.ok(err);
1212-
assert.strictEqual((err as ApiError).code, 408);
1212+
assert.strictEqual((err as ApiError).code, 503);
12131213
assert.strictEqual(
12141214
(err as ApiError).message,
1215-
'TLS handshake timeout. This may be due to CPU starvation.'
1215+
'Connection reset by peer. This suggests the remote service is temporarily unavailable or overloaded.'
12161216
);
12171217
done();
12181218
});
@@ -1234,7 +1234,7 @@ describe('common/util', () => {
12341234
assert.strictEqual((err as ApiError).code, 408);
12351235
assert.strictEqual(
12361236
(err as ApiError).message,
1237-
'TLS handshake timeout. This may be due to CPU starvation.'
1237+
'Request or TLS handshake timed out. This may be due to CPU starvation or a temporary network issue.'
12381238
);
12391239
done();
12401240
});
@@ -1254,7 +1254,7 @@ describe('common/util', () => {
12541254
assert.strictEqual((err as ApiError).code, 408);
12551255
assert.strictEqual(
12561256
(err as ApiError).message,
1257-
'TLS handshake timeout. This may be due to CPU starvation.'
1257+
'Request or TLS handshake timed out. This may be due to CPU starvation or a temporary network issue.'
12581258
);
12591259
done();
12601260
});
@@ -1276,7 +1276,7 @@ describe('common/util', () => {
12761276
assert.strictEqual((err as ApiError).code, 408);
12771277
assert.strictEqual(
12781278
(err as ApiError).message,
1279-
'TLS handshake timeout. This may be due to CPU starvation.'
1279+
'Request or TLS handshake timed out. This may be due to CPU starvation or a temporary network issue.'
12801280
);
12811281
done();
12821282
});
@@ -2016,15 +2016,25 @@ function createMakeRequestStub(
20162016
) => {
20172017
if (
20182018
err &&
2019-
(err.message?.includes('TLS handshake') ||
2020-
err.message?.includes('timed out') ||
2021-
err.message?.includes('ETIMEDOUT') ||
2022-
err.message?.includes('ECONNRESET'))
2019+
(err.message?.toLowerCase().includes('tls handshake') ||
2020+
err.message?.toLowerCase().includes('timed out') ||
2021+
err.message?.toLowerCase().includes('etimedout') ||
2022+
err.message?.toLowerCase().includes('econnreset'))
20232023
) {
2024+
let code: number;
2025+
let message: string;
2026+
if (err.message.toLowerCase().includes('econnreset')) {
2027+
code = 503;
2028+
message =
2029+
'Connection reset by peer. This suggests the remote service is temporarily unavailable or overloaded.';
2030+
} else {
2031+
code = 408;
2032+
message =
2033+
'Request or TLS handshake timed out. This may be due to CPU starvation or a temporary network issue.';
2034+
}
20242035
const tlsTimeoutError = new ApiError({
2025-
code: 408,
2026-
message:
2027-
'TLS handshake timeout. This may be due to CPU starvation.',
2036+
code,
2037+
message,
20282038
response: response as r.Response,
20292039
});
20302040
err = tlsTimeoutError;

0 commit comments

Comments
 (0)