Mintplex-Labs/anything-llm · warning

[models] returned

Error message

[models] ${modelsUrl} returned ${resp.status}

What it means

The /api models route fetched {base_url}/models (Authorization bearer when a key is set, 5s AbortController timeout) and received a non-2xx status, so it logs the status and returns an empty model list rather than erroring. The UI will simply show no models to pick.

Solutions

  1. curl the exact URL logged ([models] Fetching ...) with the same Authorization header and inspect the status/body.
  2. Correct base_url for the provider's convention (most OpenAI-compatible APIs want .../v1 as the base).
  3. Verify the API key is valid and has model-listing permission.
  4. Confirm the provider/local server is up and reachable from the service (not just from your workstation).

Example fix

# before
OPENAI_BASE_URL=https://api.example.com

# after (OpenAI-compatible providers expose /v1/models)
OPENAI_BASE_URL=https://api.example.com/v1
Defensive patterns

Strategy: validation

Validate before calling

// Preflight the models endpoint when saving provider settings:
const resp = await fetch(`${baseUrl.replace(/\/+$/, '')}/models`, {
  headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : {},
  signal: AbortSignal.timeout(5000),
});
if (!resp.ok) throw new Error(`provider /models returned ${resp.status} — check base_url and key`);

Try / catch

try { models = await fetchModels(baseUrl, apiKey); } catch { models = []; } // empty list is a config signal, not a crash

Prevention

When it happens

Trigger: base_url wrong shape (missing/extra /v1, pointing at a web page or the wrong host) so /models 404s; 401/403 when the key is wrong or required; provider 5xx or down; local server (Ollama etc.) not running when queried.

Common situations: Confusion between provider base URL conventions (with vs without /v1); reverse proxy returning 502 while the upstream restarts; expired API key; firewall blocking egress so a gateway error surfaces.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/403def6152dd39a0. Report an issue: GitHub.

Appendix: source

Thrown at open-computer/services/interface-service/routes/api.js:166

  app.get("/api/v1/models", async (req, res) => {
    const baseUrl =
      req.query.base_url || settings.OPENAI_BASE_URL || "https://api.openai.com/v1";
    const apiKey = req.query.api_key || settings.OPENAI_API_KEY;
    if (!apiKey && baseUrl === "https://api.openai.com/v1")
      return res.json({ models: [] });

    const modelsUrl =
      resolveBaseUrlForGuest(baseUrl).replace(/\/+$/, "") + "/models";
    console.log(`[models] Fetching ${modelsUrl} (from base_url=${baseUrl})`);
    try {
      const controller = new AbortController();
      const timeout = setTimeout(() => controller.abort(), 5000);
      const headers = {};
      if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
      const resp = await fetch(modelsUrl, { headers, signal: controller.signal });
      clearTimeout(timeout);
      if (!resp.ok) {
        console.warn(`[models] ${modelsUrl} returned ${resp.status}`);
        return res.json({ models: [] });
      }
      const body = await resp.json();
      const models = (body.data || []).map((m) => m.id).sort();
      console.log(
        `[models] Found ${models.length} models: ${models.slice(0, 5).join(", ")}${models.length > 5 ? "..." : ""}`,
      );
      res.json({ models });
    } catch (err) {
      console.error(`[models] Failed to fetch ${modelsUrl}: ${err.message}`);
      res.json({ models: [] });
    }
  });

  // ── Token usage ────────────────────────────────────────────────────────
  // Proxy-reported tokens (from actual OpenAI usage fields) take precedence
  // over the hypervisor's char-based estimates.  The proxy accumulates
  // session-wide; task usage tracks per-agent-invocation tool activity.

View on GitHub (pinned to 3aec848f28)