Mintplex-Labs/anything-llm · warning

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

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.

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)

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.