Mintplex-Labs/anything-llm · warning · Error
HTTP
Error message
HTTP ${resp.status}: ${(await resp.text()).slice(0, 200)} What it means
Thrown by the interface-service prompt preflight classifier when POST ${OPENAI_BASE_URL||https://api.openai.com/v1}/chat/completions returns a non-2xx status; the message embeds the status and the first 200 bytes of the response body. The call is an OpenAI-compatible chat completion with tool_choice 'required' used to route prompts to simple/plan_first/delegate_sequential modes. Importantly the surrounding try/catch downgrades this to a console.warn and a 'simple' routing decision, so the system keeps working — this error degrades planning quality rather than breaking the request.
Solutions
- Check the status/body in the message: 401 -> fix OPENAI_API_KEY; 404 -> fix OPENAI_BASE_URL (include /v1) or OPENAI_MODEL; 429 -> wait/raise limits
- Verify the chat/completions endpoint works with curl from the same machine the service runs on, including the tools+tool_choice payload
- If using a local gateway, confirm it is bound to an address reachable via resolveBaseUrlForGuest (not 127.0.0.1 of the host only)
- If you don't need planning, set SKIP_PLANNING=1 or PROMPT_PREFLIGHT=false — the preflight is skipped and this call never happens
Example fix
# before: OPENAI_BASE_URL=http://localhost:1234 (missing /v1) -> HTTP 404 export OPENAI_BASE_URL=http://localhost:1234 # after export OPENAI_BASE_URL=http://localhost:1234/v1 export OPENAI_MODEL=qwen2.5:14b # a model the gateway actually serves
Defensive patterns
Strategy: fallback
Validate before calling
async function preflightReachable(baseUrl, apiKey, model) {
try {
const r = await fetch(`${baseUrl.replace(/\/$/, '')}/chat/completions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}) },
body: JSON.stringify({ model, messages: [{ role: 'user', content: 'ping' }], max_tokens: 1 }),
});
return r.ok;
} catch { return false; }
}
// run once at service start; log loudly if false Try / catch
// Already handled internally: runPromptPreflight catches and returns { mode: 'simple', reason: `failed: ...` }.
// In your own wrapper, mirror it:
try { return await runPromptPreflight(prompt); } catch { return { mode: 'simple', reason: 'preflight unavailable' }; } Prevention
- Smoke-test OPENAI_BASE_URL (including /v1), OPENAI_API_KEY, and OPENAI_MODEL together at startup — one curl against /chat/completions with max_tokens 1
- Remember the base URL must be reachable from the guest VM (resolveBaseUrlForGuest), not just the host
- Set SKIP_PLANNING=1 in environments where the preflight model is intentionally absent so you don't depend on the degraded path
When it happens
Trigger: settings.OPENAI_API_KEY invalid or expired (401); OPENAI_BASE_URL wrong or missing the /v1 suffix (404); OPENAI_MODEL set to a name the endpoint doesn't serve (404/400); rate limits or quota exhausted (429/402); self-hosted gateway (LM Studio/Ollama/vLLM) reachable from the host but not from resolveBaseUrlForGuest's guest-side address (connection errors surface similarly); endpoints that reject the 'tools'+tool_choice payload (400).
Common situations: Swapping the model provider without updating OPENAI_BASE_URL/OPENAI_MODEL; expired API key in the service settings; local LLM server not running when the agent starts; hitting provider rate limits during heavy automated sessions.
Related errors
- ${e.message}
- LMStudio:getModelInfo
- No OpenAI API key was set.
- No OpenAI image generation API key was set.
- An error occurred while deleting the model
AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18).
Data as JSON: /api/errors/11842e6e82e70d9f.
Report an issue: GitHub.
Appendix: source
Thrown at open-computer/services/interface-service/preflight/index.js:150
type: "array",
items: { type: "string" },
description:
"For plan_first or delegate_sequential: 3-6 compact bullets to guide execution.",
},
},
required: ["mode", "reason"],
},
},
},
],
tool_choice: "required",
}),
});
clearTimeout(timeout);
if (!resp.ok) {
throw new Error(
`HTTP ${resp.status}: ${(await resp.text()).slice(0, 200)}`,
);
}
const data = await resp.json();
const args = parsePreflightToolArgs(data.choices?.[0]?.message);
const mode =
args.mode === "delegate_sequential"
? "delegate_sequential"
: args.mode === "plan_first"
? "plan_first"
: "simple";
return {
mode,
reason: String(args.reason || "model decision").slice(0, 200),
plan_hint: mode !== "simple" ? normalizePlanHint(args.plan_hint) : [],
};
} catch (err) {View on GitHub (pinned to 3aec848f28)