diff --git a/server/notification-providers/notification-provider.js b/server/notification-providers/notification-provider.js index ee04b8ee4..5360007d1 100644 --- a/server/notification-providers/notification-provider.js +++ b/server/notification-providers/notification-provider.js @@ -108,16 +108,51 @@ class NotificationProvider { * @throws {any} The error specified */ throwGeneralAxiosError(error) { - let msg = "Error: " + error + " "; + let msg = error && error.message ? error.message : String(error); - if (error.response && error.response.data) { + if (error && error.code) { + msg += ` (code=${error.code})`; + } + + if (error && error.response && error.response.status) { + msg += ` (HTTP ${error.response.status}${error.response.statusText ? " " + error.response.statusText : ""})`; + } + + if (error && error.response && error.response.data) { if (typeof error.response.data === "string") { - msg += error.response.data; + msg += " " + error.response.data; } else { - msg += JSON.stringify(error.response.data); + try { + msg += " " + JSON.stringify(error.response.data); + } catch (e) { + msg += " " + String(error.response.data); + } } } + // Expand AggregateError to show underlying causes + let agg = null; + if (error && error.name === "AggregateError" && Array.isArray(error.errors)) { + agg = error; + } else if (error && error.cause && error.cause.name === "AggregateError" && Array.isArray(error.cause.errors)) { + agg = error.cause; + } + + if (agg) { + let causes = agg.errors + .map((e) => { + let m = e && e.message ? e.message : String(e); + if (e && e.code) { + m += ` (code=${e.code})`; + } + return m; + }) + .join("; "); + msg += " - caused by: " + causes; + } else if (error && error.cause && error.cause.message) { + msg += " - cause: " + error.cause.message; + } + throw new Error(msg); } diff --git a/test/backend-test/notification-providers/test-notification-provider.js b/test/backend-test/notification-providers/test-notification-provider.js new file mode 100644 index 000000000..06ebab8e6 --- /dev/null +++ b/test/backend-test/notification-providers/test-notification-provider.js @@ -0,0 +1,34 @@ +const { describe, test } = require("node:test"); +const assert = require("node:assert"); + +const NotificationProvider = require("../../../server/notification-providers/notification-provider"); + +describe("NotificationProvider.throwGeneralAxiosError()", () => { + const provider = new NotificationProvider(); + + test("expands AggregateError causes", () => { + let err1 = new Error("connect ECONNREFUSED 127.0.0.1:443"); + err1.code = "ECONNREFUSED"; + let err2 = new Error("connect ECONNREFUSED ::1:443"); + err2.code = "ECONNREFUSED"; + + let aggErr = new AggregateError([err1, err2], "AggregateError"); + + assert.throws(() => provider.throwGeneralAxiosError(aggErr), { + message: /^AggregateError - caused by: .+/, + }); + }); + + test("expands AggregateError wrapped in error.cause", () => { + let innerErr = new Error("connect ETIMEDOUT 10.0.0.1:443"); + innerErr.code = "ETIMEDOUT"; + + let aggErr = new AggregateError([innerErr], "AggregateError"); + let outerErr = new Error("Request failed"); + outerErr.cause = aggErr; + + assert.throws(() => provider.throwGeneralAxiosError(outerErr), { + message: /^Request failed - caused by: .+/, + }); + }); +});