From 838d9a7a04b282779ba497341062d521e8f928ed Mon Sep 17 00:00:00 2001 From: Omar Nahhas Sanchez Date: Fri, 10 Apr 2026 06:30:07 +0300 Subject: [PATCH] fix: add 5s timeout to fetchCompatibleModelIds and skip upstream connections (#541) The fetchCompatibleModelIds() function had no timeout on its fetch() call, causing /v1/models to hang indefinitely when an openai-compatible provider was unreachable or slow to respond. Additionally, upstream/cross-instance connections (provider IDs containing a UUID suffix like openai-compatible-chat-XXXXXXXX) would trigger recursive /models fetches between instances, creating infinite loops. Fixes: - Add AbortController with 5-second timeout to the fetch() call - Skip dynamic model fetching for upstream/cross-instance connections (detected by UUID suffix pattern in provider ID) - Existing try/catch already handles abort errors gracefully Co-authored-by: Agent Zero --- src/app/api/v1/models/route.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/api/v1/models/route.js b/src/app/api/v1/models/route.js index 2b05760a..5017eac5 100644 --- a/src/app/api/v1/models/route.js +++ b/src/app/api/v1/models/route.js @@ -7,6 +7,9 @@ const parseOpenAIStyleModels = (data) => { return data?.data || data?.models || data?.results || []; }; +// Matches provider IDs that are upstream/cross-instance connections (contain a UUID suffix) +const UPSTREAM_CONNECTION_RE = /[-_][0-9a-f]{8,}$/i; + async function fetchCompatibleModelIds(connection) { if (!connection?.apiKey) return []; @@ -37,11 +40,15 @@ async function fetchCompatibleModelIds(connection) { } try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 5000); const response = await fetch(url, { method: "GET", headers, cache: "no-store", + signal: controller.signal, }); + clearTimeout(timeoutId); if (!response.ok) return []; @@ -167,7 +174,7 @@ export async function GET() { ) : providerModels.map((model) => model.id); - if (isCompatibleProvider && rawModelIds.length === 0) { + if (isCompatibleProvider && rawModelIds.length === 0 && !UPSTREAM_CONNECTION_RE.test(providerId)) { rawModelIds = await fetchCompatibleModelIds(conn); }