Mintplex-Labs/anything-llm · error · Error

res.statusText || "Error finding custom models."

Error message

res.statusText || "Error finding custom models."

What it means

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.

Source

Thrown at frontend/src/models/system.js:617

      setTimeout(() => {
        controller.abort("Request timed out.");
      }, timeout);
    }

    return fetch(`${API_BASE}/system/custom-models`, {
      method: "POST",
      headers: baseHeaders(),
      signal: controller.signal,
      body: JSON.stringify({
        provider,
        apiKey,
        basePath,
        options: options || {},
      }),
    })
      .then((res) => {
        if (!res.ok) {
          throw new Error(res.statusText || "Error finding custom models.");
        }
        return res.json();
      })
      .catch((e) => {
        console.error(e);
        return { models: [], error: e.message };
      });
  },
  chats: async (offset = 0) => {
    return await fetch(`${API_BASE}/system/workspace-chats`, {
      method: "POST",
      headers: baseHeaders(),
      body: JSON.stringify({ offset }),
    })
      .then((res) => res.json())
      .catch((e) => {
        console.error(e);
        return [];

View on GitHub (pinned to 526360e320)

Solutions

  1. Verify the provider API key is valid by using it directly against the provider's own /models endpoint with curl.
  2. Confirm basePath matches the provider's OpenAI-compatible root (no trailing /v1/ double-slash, correct region for Azure).
  3. Pass a larger timeout (or null) to customModels so the AbortController does not fire prematurely.
  4. Inspect the backend /system/custom-models handler logs for the upstream status code being relayed.

Example fix

// before
if (!res.ok) {
  throw new Error(res.statusText || "Error finding custom models.");
}

// after
if (!res.ok) {
  let detail = res.statusText;
  try { const body = await res.json(); detail = body?.error || detail; } catch {}
  throw new Error(detail || `Error finding custom models (HTTP ${res.status}).`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate provider config shape before calling customModels.
function isValidProviderConfig(provider, apiKey, basePath) {
  if (!provider || typeof provider !== 'string') return false;
  if (!apiKey || apiKey.trim().length < 10) return false;
  if (basePath && !/^https?:\/\//.test(basePath)) return false;
  return true;
}

Type guard

function isCustomModelsResult(x): x is { models: unknown[]; error?: string } {
  return x && Array.isArray(x.models);
}

Try / catch

const { models, error } = await System.customModels(provider, apiKey, basePath, timeout);
if (models.length === 0 && error) {
  setProviderError(error);
  return;
}
setAvailableModels(models);

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13). Data as JSON: /api/errors/770f06f26663cbbc. Report an issue: GitHub.