Mintplex-Labs/anything-llm · error · Error
HTTP error! status
Error message
HTTP error! status: ${response.status} What it means
Thrown inside executeApiCall when the fetch completes but response.ok is false — i.e. the remote server answered with a non-2xx HTTP status. Only the numeric status is included (no body or statusText), so the response payload that usually explains the failure is discarded; the outer catch immediately rewraps this into 'API Call failed: HTTP error! status: N'. The introspect log 'Request failed with status N' is emitted just before the throw.
Solutions
- Reproduce the exact request outside the flow (curl with the same method, headers, body) and read the response body the flow hides.
- Check the introspect log lines ('Sending body to <url>') to see the resolved URL and body — fix any empty/uninterpolated variables.
- For 401/403, correct the Authorization header or API-key header the block config produces.
- For 429/5xx, retry later or add error handling upstream; the block itself has no retry.
Defensive patterns
Strategy: retry
Validate before calling
async function apiCallPrecheck(url) {
const parsed = new URL(url); // throws early on malformed URLs
if (!/^https?:$/.test(parsed.protocol)) throw new Error("URL must be http(s)");
return true;
} Try / catch
const RETRYABLE = new Set([429, 500, 502, 503, 504]);
async function callWithRetry(exec, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await exec();
} catch (e) {
const m = e.message.match(/HTTP error! status: (\d+)/);
if (!m || !RETRYABLE.has(Number(m[1])) || i === attempts - 1) throw e;
await new Promise((r) => setTimeout(r, 2 ** i * 500));
}
}
} Prevention
- Test the block's exact method/URL/headers/body with curl before enabling the flow in production.
- Fill auth credentials via flow variables so headers can never ship empty.
- Respect 429 Retry-After; never retry 4xx other than 429 — those are config bugs, not transient failures.
When it happens
Trigger: An Agent Flow API Call block whose URL returns 401/403 (bad or missing auth header), 404 (wrong path or uninterpolated {{variable}} in the URL), 400 (validation error), 429 (rate limit), or 5xx (remote failure). Any non-2xx from the target server triggers it.
Common situations: API key placeholder never filled in so the header is empty; URL built from a flow variable that resolved to undefined; hitting an endpoint that requires a different method than configured; rate-limited third-party APIs; staging endpoint returning 502 while down; JSON body sent to an endpoint expecting form data.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- API Call failed
- An error occurred while deleting the model
- Could not validate login.
- data.message || "Could not update slash command preset."
- data.message || "Error creating slash command preset."
AI-assisted analysis of Mintplex-Labs/anything-llm@f92433b4ea (2026-08-18).
Data as JSON: /api/errors/14217f59d48ebf34.
Report an issue: GitHub.
Appendix: source
Thrown at server/utils/agentFlows/executors/api-call.js:49
} else if (body?.trim()) {
throw new Error(
"The request body of this API Call block is not valid JSON. Open the flow in the Agent Builder and check the body for syntax errors such as missing commas, brackets, or quotes."
);
}
requestConfig.headers["Content-Type"] = "application/json";
} else if (bodyType === "text") {
requestConfig.body = String(body);
} else {
requestConfig.body = body;
}
}
try {
introspect(`Sending body to ${url}: ${requestConfig?.body || "No body"}`);
const response = await fetch(url, requestConfig);
if (!response.ok) {
introspect(`Request failed with status ${response.status}`);
throw new Error(`HTTP error! status: ${response.status}`);
}
introspect(`API call completed`);
const responseText = await response.text();
try {
// JSON bodies parse into values; anything else (plain text, HTML,
// empty bodies) is passed through verbatim. We intentionally avoid
// safeJsonParse here so non-JSON bodies are never "repaired" into
// invented JSON or reduced to an embedded JSON substring.
return JSON.parse(responseText);
} catch {
return responseText;
}
} catch (error) {
console.error(error);
throw new Error(`API Call failed: ${error.message}`);
}
}View on GitHub (pinned to f92433b4ea)