Mintplex-Labs/anything-llm · error
- . params: )}
Error message
${res.status} - ${res.statusText}. params: ${JSON.stringify({ auth: this.middleTruncate(process.env.AGENT_SEARCHAPI_API_KEY, 5), q: query })} What it means
Thrown inside the SearchApi branch of the web-browsing plugin when fetch to https://www.searchapi.io/api/v1/search returns non-ok. The request authenticates with 'Authorization: Bearer <AGENT_SEARCHAPI_API_KEY>' plus an AnythingLLM source header; the error message includes status, statusText, query, and the key middle-truncated to 5 chars. The adjacent .catch converts it to a logged 'SearchApi Error' and an error string for the agent, so it normally appears as 'There was an error searching for content. ...'.
Solutions
- Set AGENT_SEARCHAPI_API_KEY to a valid searchapi.io key and restart the server; unset keys for providers you do not use so the agent cannot pick them.
- Map the status: 401/403 -> key problem; 429 -> credits/rate limit, check dashboard; 400 -> invalid engine parameter.
- Test the key out-of-band with the same Bearer header to isolate agent config from provider state.
Example fix
# before AGENT_SEARCHAPI_API_KEY= # empty -> 401 - Unauthorized # after AGENT_SEARCHAPI_API_KEY=<searchapi.io key> systemctl restart anythingllm # or docker restart
Defensive patterns
Strategy: validation
Validate before calling
const KEY = process.env.AGENT_SEARCHAPI_API_KEY;
if (!KEY) {
throw new Error("AGENT_SEARCHAPI_API_KEY not set — add it to the server .env and restart");
}
// optional cheap pre-flight to fail fast with the provider's own status:
const probe = await fetch("https://www.searchapi.io/api/v1/search?engine=google_q=q_test", { headers: { Authorization: `Bearer ${KEY}` } });
if (probe.status === 401 || probe.status === 403) throw new Error("SearchApi key rejected"); Try / catch
const out = await webSearch(query);
if (typeof out === "string" && out.includes("SearchApi Error")) {
if (/40[13]/.test(out)) rotateKey("AGENT_SEARCHAPI_API_KEY");
else if (out.includes("429")) scheduleRetry(query, 60_000); // credits/rate limit
else inspectParams(out);
} Prevention
- Use a dedicated searchapi.io key and monitor its credit balance.
- Never reuse another provider's key in AGENT_SEARCHAPI_API_KEY.
- Restart after key rotation; validate engine params against searchapi.io docs.
When it happens
Trigger: AGENT_SEARCHAPI_API_KEY absent, invalid, or from the wrong provider (401/403); SearchApi.io credits exhausted or rate-limited (429); unsupported engine value in params (400); searchapi.io service errors (5xx).
Common situations: Mixing up keys between SerpApi/SearchApi/Serper.dev env vars; expired credits on the SearchApi plan; .env edited without restarting the server.
Related errors
- - . params: )}
- - . params: )}
- - . params: )}
- Access denied - path outside allowed directories.
- Community Hub connection key not found
AI-assisted analysis of Mintplex-Labs/anything-llm@a145d4d87d (2026-08-18).
Data as JSON: /api/errors/5cb3e634a50b4cf2.
Report an issue: GitHub.
Appendix: source
Thrown at server/utils/agents/aibitat/plugins/web-browsing.js:462
const engine = process.env.AGENT_SEARCHAPI_ENGINE;
const params = new URLSearchParams({
engine: engine,
q: query,
});
const url = `https://www.searchapi.io/api/v1/search?${params.toString()}`;
const { response, error } = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.AGENT_SEARCHAPI_API_KEY}`,
"Content-Type": "application/json",
"X-SearchApi-Source": "AnythingLLM",
},
})
.then((res) => {
if (res.ok) return res.json();
throw new Error(
`${res.status} - ${res.statusText}. params: ${JSON.stringify({ auth: this.middleTruncate(process.env.AGENT_SEARCHAPI_API_KEY, 5), q: query })}`
);
})
.then((data) => {
return { response: data, error: null };
})
.catch((e) => {
this.super.handlerProps.log(`SearchApi Error: ${e.message}`);
return { response: null, error: e.message };
});
if (error)
return `There was an error searching for content. ${error}`;
const data = [];
if (response.hasOwnProperty("knowledge_graph"))
data.push(response.knowledge_graph?.description);
if (response.hasOwnProperty("answer_box"))
data.push(response.answer_box?.answer);View on GitHub (pinned to a145d4d87d)