{"record":{"id":"5cd037ea51a9f57c","repo":"n8n-io/n8n","slug":"failed-to-list-provider-models-status-respon","errorCode":null,"errorMessage":"Failed to list ${provider} models (status ${response.status})${body ? `: ${body.slice(0, 500)}` : ''}","messagePattern":"Failed to list (.+?) models \\(status (.+?)\\)(.+?)` : ''\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/ai-utilities/src/model-discovery/request.ts","lineNumber":26,"sourceCode":"\theaders: Record<string, string>,\n\toptions: ListModelsOptions,\n\tprovider: string,\n): Promise<unknown> {\n\tconst fetchFn = options.fetch ?? globalThis.fetch;\n\tconst response = await fetchFn(url, {\n\t\tmethod: 'GET',\n\t\theaders: { ...headers, ...options.headers },\n\t});\n\tif (!response.ok) {\n\t\tif (response.status === 401 || response.status === 403) {\n\t\t\tthrow new UserError(\n\t\t\t\t\"Models couldn't be loaded. Check that the selected credential is valid and has the required permissions, then try again.\",\n\t\t\t\t{ shouldReport: false },\n\t\t\t);\n\t\t}\n\n\t\tconst body = await response.text().catch(() => '');\n\t\tthrow new Error(\n\t\t\t`Failed to list ${provider} models (status ${response.status})${body ? `: ${body.slice(0, 500)}` : ''}`,\n\t\t);\n\t}\n\treturn await response.json();\n}\n\n/** Resolve the API base: caller override or the provider default, without a trailing slash. */\nexport function baseUrl(options: ListModelsOptions, fallback: string): string {\n\treturn (options.baseURL ?? fallback).replace(/\\/+$/, '');\n}\n\nexport function bearerHeaders(options: ListModelsOptions): Record<string, string> {\n\treturn { Authorization: `Bearer ${options.apiKey}` };\n}\n\nexport function byName(a: ProviderModel, b: ProviderModel): number {\n\treturn a.name.localeCompare(b.name);\n}","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/ai-utilities/src/model-discovery/request.ts#L8-L44","documentation":"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'.","triggerScenarios":"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.","commonSituations":"Rate limiting on the models endpoint; provider outage; misconfigured baseURL override; proxy/gateway returning an unexpected status; region-specific endpoint unavailable.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"function isModelListHttpError(e: unknown): boolean {\n  return e instanceof Error && /Failed to list .* models \\(status \\d+\\)/.test(e.message);\n}","tryCatchPattern":"for (const delay of [1000, 3000, 10000]) {\n  try {\n    return await listModelsForProvider(provider, opts);\n  } catch (e) {\n    if (!isModelListHttpError(e)) throw e;\n    if (/status 429|status 5\\d\\d/.test(e.message)) await new Promise((r) => setTimeout(r, delay));\n    else throw e;\n  }\n}","preventionTips":["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."],"tags":["model-discovery","network","http","ai-utilities"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}