diff --git a/src/app/(dashboard)/dashboard/providers/page.tsx b/src/app/(dashboard)/dashboard/providers/page.tsx index 172a138137..d38dafb7b4 100644 --- a/src/app/(dashboard)/dashboard/providers/page.tsx +++ b/src/app/(dashboard)/dashboard/providers/page.tsx @@ -189,23 +189,35 @@ export default function ProvidersPage() { if (testingMode) return; setTestingMode(mode === "provider" ? providerId : mode); setTestResults(null); + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 90_000); // 90s max try { const res = await fetch("/api/providers/test-batch", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ mode, providerId }), + signal: controller.signal, }); - const data = await res.json(); + let data: any; + try { + data = await res.json(); + } catch { + // Response body is not valid JSON (e.g. truncated due to timeout) + data = { error: t("providerTestFailed"), results: [], summary: null }; + } setTestResults(data); - if (data.summary) { + if (data?.summary) { const { passed, failed, total } = data.summary; if (failed === 0) notify.success(t("allTestsPassed", { total })); else notify.warning(t("testSummary", { passed, failed, total })); } - } catch (error) { - setTestResults({ error: t("providerTestFailed") }); - notify.error(t("providerTestFailed")); + } catch (error: any) { + const isAbort = error?.name === "AbortError"; + const msg = isAbort ? t("providerTestTimeout") : t("providerTestFailed"); + setTestResults({ error: msg, results: [], summary: null }); + notify.error(msg); } finally { + clearTimeout(timeoutId); setTestingMode(null); } }; @@ -1041,17 +1053,23 @@ function ProviderTestResultsView({ results }) { const t = useTranslations("providers"); const tc = useTranslations("common"); - if (results.error && !results.results) { + // Guard: never crash on malformed/null results (would trigger error boundary) + if (!results || typeof results !== "object") { + return null; + } + + if (results.error && (!results.results || results.results.length === 0)) { return (
{results.error}
+{String(results.error)}