n8n-io/n8n · error · Error
Failed to list ${provider} models (status ${response.status}
Error message
Failed to list ${provider} models (status ${response.status})${body ? `: ${body.slice(0, 500)}` : ''} What it means
The fallback branch of the model-listing request helper: the response is non-OK and NOT 401/403, so it's a transport/provider error (4xx/5xx). It reads up to 500 chars of the response body and throws an Error naming the provider and HTTP status, so the user can see the underlying failure rather than a generic 'models could not be loaded'.
Source
Thrown at packages/@n8n/ai-utilities/src/model-discovery/request.ts:26
headers: Record<string, string>,
options: ListModelsOptions,
provider: string,
): Promise<unknown> {
const fetchFn = options.fetch ?? globalThis.fetch;
const response = await fetchFn(url, {
method: 'GET',
headers: { ...headers, ...options.headers },
});
if (!response.ok) {
if (response.status === 401 || response.status === 403) {
throw new UserError(
"Models couldn't be loaded. Check that the selected credential is valid and has the required permissions, then try again.",
{ shouldReport: false },
);
}
const body = await response.text().catch(() => '');
throw new Error(
`Failed to list ${provider} models (status ${response.status})${body ? `: ${body.slice(0, 500)}` : ''}`,
);
}
return await response.json();
}
/** Resolve the API base: caller override or the provider default, without a trailing slash. */
export function baseUrl(options: ListModelsOptions, fallback: string): string {
return (options.baseURL ?? fallback).replace(/\/+$/, '');
}
export function bearerHeaders(options: ListModelsOptions): Record<string, string> {
return { Authorization: `Bearer ${options.apiKey}` };
}
export function byName(a: ProviderModel, b: ProviderModel): number {
return a.name.localeCompare(b.name);
}View on GitHub (pinned to 5ac6606e81)
Solutions
- Read the status + body in the message: 429 → slow down / retry with backoff; 5xx → provider outage, retry later; 404 → fix baseURL.
- If using a custom baseURL, confirm it points at the provider's models endpoint.
- Retry transient failures; surface persistent ones to the provider's status page.
Defensive patterns
Strategy: retry
Type guard
function isModelListHttpError(e: unknown): boolean {
return e instanceof Error && /Failed to list .* models \(status \d+\)/.test(e.message);
} Try / catch
for (const delay of [1000, 3000, 10000]) {
try {
return await listModelsForProvider(provider, opts);
} catch (e) {
if (!isModelListHttpError(e)) throw e;
if (/status 429|status 5\d\d/.test(e.message)) await new Promise((r) => setTimeout(r, delay));
else throw e;
}
} Prevention
- Retry 429/5xx with exponential backoff; fail fast on 4xx (except 429).
- If using a custom baseURL, confirm it points at the provider's models endpoint.
- Cache model lists to avoid hammering the endpoint during dropdown refreshes.
When it happens
Trigger: Provider returns 429 (rate limit), 500/502/503 (outage), 404 (wrong baseURL), 400 (malformed request), or a network-level non-OK status; a custom baseURL pointing to the wrong endpoint; provider model API temporarily down.
Common situations: Rate limiting on the models endpoint; provider outage; misconfigured baseURL override; proxy/gateway returning an unexpected status; region-specific endpoint unavailable.
Related errors
- Unknown model discovery provider: "${provider}"
- Webhook request failed: ${response.status} ${response.status
- LangSmith sessions lookup failed: ${res.status} ${await res.
- LangSmith runs/query failed: ${res.status} ${await res.text(
- n8n API ${method} ${path} failed (${res.status}): ${text}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/5cd037ea51a9f57c.
Report an issue: GitHub.