From 93be40c397083c4731a8246fd3365a25214e4bb0 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 29 Jan 2026 23:45:52 +0000 Subject: [PATCH] Handle fetch failed message as transient network error --- src/infra/unhandled-rejections.test.ts | 5 +++++ src/infra/unhandled-rejections.ts | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/infra/unhandled-rejections.test.ts b/src/infra/unhandled-rejections.test.ts index 1ec144ba1..0a6a71530 100644 --- a/src/infra/unhandled-rejections.test.ts +++ b/src/infra/unhandled-rejections.test.ts @@ -81,6 +81,11 @@ describe("isTransientNetworkError", () => { expect(isTransientNetworkError(error)).toBe(true); }); + it('returns true for Error with "TypeError: fetch failed" message', () => { + const error = new Error("TypeError: fetch failed"); + expect(isTransientNetworkError(error)).toBe(true); + }); + it("returns true for fetch failed with network cause", () => { const cause = Object.assign(new Error("getaddrinfo ENOTFOUND"), { code: "ENOTFOUND" }); const error = Object.assign(new TypeError("fetch failed"), { cause }); diff --git a/src/infra/unhandled-rejections.ts b/src/infra/unhandled-rejections.ts index d186c6a78..1fa3a779c 100644 --- a/src/infra/unhandled-rejections.ts +++ b/src/infra/unhandled-rejections.ts @@ -1,6 +1,6 @@ import process from "node:process"; -import { extractErrorCode, formatUncaughtError } from "./errors.js"; +import { extractErrorCode, formatErrorMessage, formatUncaughtError } from "./errors.js"; type UnhandledRejectionHandler = (reason: unknown) => boolean; @@ -88,6 +88,14 @@ export function isTransientNetworkError(err: unknown): boolean { return true; } + // Some environments wrap fetch failures as generic Errors (e.g., "TypeError: fetch failed") + const message = formatErrorMessage(err).toLowerCase(); + if (message.includes("fetch failed")) { + const cause = getErrorCause(err); + if (cause) return isTransientNetworkError(cause); + return true; + } + // Check the cause chain recursively const cause = getErrorCause(err); if (cause && cause !== err) {