From 424b950856a02aca84a31dcdb951f105e4042426 Mon Sep 17 00:00:00 2001 From: "Bob.Hou" Date: Fri, 21 Aug 2026 00:21:07 +0800 Subject: [PATCH] fix(api): classify OAuth probe timeout as network_error (#10663) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged — locally validated (focused tests green, gates green). Clean, minimal classification fix. Thanks! --- src/app/api/providers/[id]/test/route.ts | 1 + ...ction-test-timed-out-network-error.test.ts | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tests/unit/connection-test-timed-out-network-error.test.ts diff --git a/src/app/api/providers/[id]/test/route.ts b/src/app/api/providers/[id]/test/route.ts index f8afbb6cb0..36effb38a6 100644 --- a/src/app/api/providers/[id]/test/route.ts +++ b/src/app/api/providers/[id]/test/route.ts @@ -153,6 +153,7 @@ export function classifyFailure({ normalized.includes("fetch failed") || normalized.includes("network") || normalized.includes("timeout") || + normalized.includes("timed out") || normalized.includes("econn") || normalized.includes("enotfound") || normalized.includes("socket") diff --git a/tests/unit/connection-test-timed-out-network-error.test.ts b/tests/unit/connection-test-timed-out-network-error.test.ts new file mode 100644 index 0000000000..fbba8ba0b4 --- /dev/null +++ b/tests/unit/connection-test-timed-out-network-error.test.ts @@ -0,0 +1,29 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +const { classifyFailure } = await import("../../src/app/api/providers/[id]/test/route.ts"); + +// The OAuth probe's own abort message is "Test timed out after Xs" (route.ts's +// AbortSignal.timeout handling), which contains "timed out" but not "timeout" — +// classifyFailure must classify it as network_error, not the generic upstream_error +// fallback, so a transient probe timeout doesn't paint the connection permanently red. +test("classifyFailure maps an OAuth-probe 'timed out' message to network_error", () => { + const diagnosis = classifyFailure({ + error: "Test timed out after 30s", + statusCode: null, + provider: "some-oauth-provider", + }); + + assert.equal(diagnosis.type, "network_error"); + assert.equal(diagnosis.code, "network_error"); +}); + +test("classifyFailure still maps the existing 'timeout' substring to network_error", () => { + const diagnosis = classifyFailure({ + error: "connect ETIMEDOUT — timeout while probing upstream", + statusCode: null, + provider: "some-oauth-provider", + }); + + assert.equal(diagnosis.type, "network_error"); +});