Mintplex-Labs/anything-llm · error · RetryError
error.message
Error message
error.message
What it means
LiteLLMProvider.stream() wraps failures from the streaming tool-call path (tooledStream, used only when native tool calling is enabled) against a LiteLLM proxy: OpenAI RateLimitError, InternalServerError, or any APIError is rethrown as RetryError with the original message; AuthenticationError is rethrown raw; unknown errors pass through. The raw error is first logged via console.error(error.message, error), so the server log holds the full SDK error object even though the thrown RetryError keeps only the message. RetryError is aibitat's 'safe to retry' signal (error.js:13). Since APIError is the SDK base for all HTTP errors, a bad model name (404) or 400 from the proxy is wrapped identically to transient 429/5xx.
Source
Thrown at server/utils/agents/aibitat/providers/litellm.js:103
try {
return await tooledStream(
this.client,
this.model,
messages,
functions,
eventHandler,
{ provider: this }
);
} catch (error) {
console.error(error.message, error);
if (error instanceof OpenAI.AuthenticationError) throw error;
if (
error instanceof OpenAI.RateLimitError ||
error instanceof OpenAI.InternalServerError ||
error instanceof OpenAI.APIError
) {
throw new RetryError(error.message);
}
throw error;
}
}
/**
* Create a non-streaming completion with tool calling support.
* Uses native tool calling when enabled via ENV, otherwise falls back to UnTooled.
*/
async complete(messages, functions = []) {
const useNative = await this.supportsNativeToolCalling();
if (!useNative) {
return await UnTooled.prototype.complete.call(
this,
messages,
functions,
this.#handleFunctionCallChat.bind(this)View on GitHub (pinned to 3aec848f28)
Solutions
- Read the server console log first — this site prints the full error object; the status code in the message tells you 4xx (config) vs 429/5xx (transient)
- Verify this.model is a valid deployment name on the proxy (litellm `model_list`) and fix LITE_LLM_MODEL_PREF or the agent's model config
- Confirm LITE_LLM_BASE_PATH points at the proxy root (e.g. http://host:4000) so /v1/chat/completions resolves
- For 429 with cooldowns, raise the LiteLLM router rpm/tpm limits or wait out the cooldown window, then re-run the chat
- For 500s, inspect the LiteLLM proxy logs to see which upstream failed and fix that provider's credentials
Example fix
// before: model pref drifts from proxy deployments
// LITE_LLM_MODEL_PREF=gpt-4o (not in proxy config.yaml -> 400 -> RetryError)
// after
// config.yaml model_list entry: model_name: agent-fast, litellm_params: {model: gpt-4o-mini}
// LITE_LLM_MODEL_PREF=agent-fast Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: model must exist on the proxy and key must work
if (!process.env.LITE_LLM_BASE_PATH) throw new Error("LITE_LLM_BASE_PATH not set");
const r = await fetch(`${process.env.LITE_LLM_BASE_PATH}/v1/models`, {
headers: { Authorization: `Bearer ${process.env.LITE_LLM_API_KEY ?? ""}` },
});
if (!r.ok) throw new Error(`LiteLLM proxy pre-flight failed (${r.status})`); Type guard
const { RetryError } = require("./server/utils/agents/aibitat/error.js");
const isRetryError = (e) => e instanceof RetryError;
const isProxyTransient = (e) => isRetryError(e) && /429|500|502|503/.test(String(e.message)); Try / catch
try {
return await provider.stream(messages, functions, eventHandler);
} catch (error) {
if (error instanceof OpenAI.AuthenticationError) throw error; // key wrong — never retry
if (error instanceof RetryError) {
if (isProxyTransient(error)) return withBackoff(() => provider.stream(messages, functions, eventHandler));
throw error; // 400/404 = deployment name wrong
}
throw error;
} Prevention
- Keep LITE_LLM_MODEL_PREF in lockstep with the proxy's config.yaml model_list aliases; validate on deploy
- Set generous rpm/tpm and cooldown settings in the LiteLLM router so agent bursts don't trip 429s
- Monitor the proxy logs — this provider logs the raw error to console, so correlate timestamps
- Only enable native tool calling once the proxy deployment is verified to support it
When it happens
Trigger: Streaming chat.completions.create against process.env.LITE_LLM_BASE_PATH where the proxy returns 429 (LiteLLM router rate limit/cooldown), 500/502 when the mapped upstream provider errors, 400/404 when this.model (LITE_LLM_MODEL_PREF or config.model) is not a valid LiteLLM deployment name, or 401 when LITE_LLM_API_KEY does not match the proxy's master key (rethrown unwrapped). Only fires on the tooledStream branch; the UnTooled fallback path has its own handling.
Common situations: LITE_LLM_MODEL_PREF names a model alias not configured in the proxy's config.yaml; proxy master key rotated but LITE_LLM_API_KEY stale; upstream OpenAI/Anthropic key expired so LiteLLM returns 500; proxy rate-limit budget exhausted by other clients sharing the proxy.
Related errors
AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18).
Data as JSON: /api/errors/c96971e461a1165a.
Report an issue: GitHub.