{"record":{"id":"770f06f26663cbbc","repo":"Mintplex-Labs/anything-llm","slug":"res-statustext-error-finding-custom-models","errorCode":null,"errorMessage":"res.statusText || \"Error finding custom models.\"","messagePattern":"res\\.statusText \\|\\| \"Error finding custom models\\.\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/models/system.js","lineNumber":617,"sourceCode":"      setTimeout(() => {\n        controller.abort(\"Request timed out.\");\n      }, timeout);\n    }\n\n    return fetch(`${API_BASE}/system/custom-models`, {\n      method: \"POST\",\n      headers: baseHeaders(),\n      signal: controller.signal,\n      body: JSON.stringify({\n        provider,\n        apiKey,\n        basePath,\n        options: options || {},\n      }),\n    })\n      .then((res) => {\n        if (!res.ok) {\n          throw new Error(res.statusText || \"Error finding custom models.\");\n        }\n        return res.json();\n      })\n      .catch((e) => {\n        console.error(e);\n        return { models: [], error: e.message };\n      });\n  },\n  chats: async (offset = 0) => {\n    return await fetch(`${API_BASE}/system/workspace-chats`, {\n      method: \"POST\",\n      headers: baseHeaders(),\n      body: JSON.stringify({ offset }),\n    })\n      .then((res) => res.json())\n      .catch((e) => {\n        console.error(e);\n        return [];","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/frontend/src/models/system.js#L599-L635","documentation":"Thrown by System.customModels when POST /system/custom-models returns non-2xx. This endpoint probes a third-party LLM provider (given provider, apiKey, basePath) and returns the list of available models. The request is wrapped in an AbortController with an optional caller-supplied timeout. The .catch returns { models: [], error } so the UI can render an empty model list with a reason.","triggerScenarios":"Supplying an invalid or revoked provider API key (401 from the upstream provider surfaced through the backend), pointing basePath at a non-OpenAI-compatible endpoint, the AbortController firing because the caller passed a very small timeout, or the backend being unable to reach the provider (DNS/proxy).","commonSituations":"User pastes a truncated API key in the LLM provider settings; basePath has a trailing slash or wrong API version; corporate egress proxy blocks the provider; provider catalog endpoint changed (e.g. Azure vs OpenAI paths); timeout default too aggressive for slow providers.","solutions":["Verify the provider API key is valid by using it directly against the provider's own /models endpoint with curl.","Confirm basePath matches the provider's OpenAI-compatible root (no trailing /v1/ double-slash, correct region for Azure).","Pass a larger timeout (or null) to customModels so the AbortController does not fire prematurely.","Inspect the backend /system/custom-models handler logs for the upstream status code being relayed."],"exampleFix":"// before\nif (!res.ok) {\n  throw new Error(res.statusText || \"Error finding custom models.\");\n}\n\n// after\nif (!res.ok) {\n  let detail = res.statusText;\n  try { const body = await res.json(); detail = body?.error || detail; } catch {}\n  throw new Error(detail || `Error finding custom models (HTTP ${res.status}).`);\n}","handlingStrategy":"try-catch","validationCode":"// Validate provider config shape before calling customModels.\nfunction isValidProviderConfig(provider, apiKey, basePath) {\n  if (!provider || typeof provider !== 'string') return false;\n  if (!apiKey || apiKey.trim().length < 10) return false;\n  if (basePath && !/^https?:\\/\\//.test(basePath)) return false;\n  return true;\n}","typeGuard":"function isCustomModelsResult(x): x is { models: unknown[]; error?: string } {\n  return x && Array.isArray(x.models);\n}","tryCatchPattern":"const { models, error } = await System.customModels(provider, apiKey, basePath, timeout);\nif (models.length === 0 && error) {\n  setProviderError(error);\n  return;\n}\nsetAvailableModels(models);","preventionTips":["Pass a generous timeout (or null) for slow providers to avoid AbortController-induced failures.","Strip trailing slashes from basePath before calling.","Treat an empty models array with an error string as a hard failure in the UI, not a successful empty catalog."],"tags":["frontend","api-client","llm-provider","http","network"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}