From 7c9abfbe8413b513f877e56d966a0cddb7708bf3 Mon Sep 17 00:00:00 2001 From: Nikhil Gupta Date: Fri, 6 Oct 2023 17:54:18 -0400 Subject: [PATCH] fix: surface 'cause' for undici network errors (#642) --- src/fetch-wrapper.ts | 15 ++++++++++++++- test/request.test.ts | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/fetch-wrapper.ts b/src/fetch-wrapper.ts index 52c278828..d3cb99737 100644 --- a/src/fetch-wrapper.ts +++ b/src/fetch-wrapper.ts @@ -131,7 +131,20 @@ export default function fetchWrapper( if (error instanceof RequestError) throw error; else if (error.name === "AbortError") throw error; - throw new RequestError(error.message, 500, { + let message = error.message; + + // undici throws a TypeError for network errors + // and puts the error message in `error.cause` + // https://github.com/nodejs/undici/blob/e5c9d703e63cd5ad691b8ce26e3f9a81c598f2e3/lib/fetch/index.js#L227 + if ( + error instanceof TypeError && + "cause" in error && + typeof error.cause === "string" + ) { + message = error.cause; + } + + throw new RequestError(message, 500, { request: requestOptions, }); }); diff --git a/test/request.test.ts b/test/request.test.ts index 3025c715c..b1f957d4f 100644 --- a/test/request.test.ts +++ b/test/request.test.ts @@ -439,6 +439,26 @@ x//0u+zd/R/QRUzLOw4N72/Hu+UG6MNt5iDZFCtapRaKt6OvSBwy8w== }); }); + it("Request TypeError error", () => { + const mock = fetchMock.sandbox().get("https://127.0.0.1:8/", { + throws: Object.assign(new TypeError("fetch failed"), { cause: "bad" }), + }); + + // port: 8 // officially unassigned port. See https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers + return request("GET https://127.0.0.1:8/", { + request: { + fetch: mock, + }, + }) + .then(() => { + throw new Error("should not resolve"); + }) + .catch((error) => { + expect(error.status).toEqual(500); + expect(error.message).toEqual("bad"); + }); + }); + it("custom user-agent", () => { const mock = fetchMock .sandbox()