{"record":{"id":"17732233dadd8621","repo":"n8n-io/n8n","slug":"failed-to-fetch-templates-response-status-re","errorCode":null,"errorMessage":"Failed to fetch templates: ${response.status} ${response.statusText}","messagePattern":"Failed to fetch templates: (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/ai-workflow-builder.ee/src/tools/web/templates.ts","lineNumber":81,"sourceCode":"export async function fetchTemplateList(query: {\n\tsearch?: string;\n\tcategory?: Category;\n\trows?: number;\n\tnodes?: string;\n}): Promise<TemplateSearchResponse> {\n\tconst queryString = buildSearchQueryString(query);\n\tconst url = `${N8N_API_BASE_URL}/templates/search${queryString ? `?${queryString}` : ''}`;\n\n\tconst response = await fetch(url, {\n\t\tmethod: 'GET',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t\tAccept: 'application/json',\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch templates: ${response.status} ${response.statusText}`);\n\t}\n\n\tconst data: unknown = await response.json();\n\tif (!isTemplateSearchResponse(data)) {\n\t\tthrow new Error('Invalid response format from templates API');\n\t}\n\treturn data;\n}\n\n/**\n * Fetch a specific workflow template by ID from n8n API\n */\nexport async function fetchTemplateByID(id: number): Promise<TemplateFetchResponse> {\n\tconst url = `${N8N_API_BASE_URL}/workflows/templates/${id}`;\n\n\tconst response = await fetch(url, {\n\t\tmethod: 'GET',\n\t\theaders: {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/ai-workflow-builder.ee/src/tools/web/templates.ts#L63-L99","documentation":"fetchTemplateList in tools/web/templates.ts issues GET https://api.n8n.io/api/templates/search and throws a plain Error with the HTTP status and statusText when response.ok is false. This is an external API failure: the templates backend returned a non-2xx code (or the fetch itself resolved to an error response).","triggerScenarios":"api.n8n.io returns 4xx/5xx: 429 rate limit, 5xx outage, 404 from a malformed query string, or a network-layer error surfaced as a non-OK response.","commonSituations":"n8n template service outage; client network restricted or offline; aggressive polling triggering rate limits; bad search/category/nodes query parameters producing a 4xx; corporate proxy returning a block page.","solutions":["Decode the HTTP status: 429 -> back off and retry; 5xx -> transient, retry with jitter; 4xx -> validate query parameters.","Retry with exponential backoff (e.g. 3 attempts) for 429/5xx.","Fall back to a cached/local template list or skip template enrichment.","Verify network egress to api.n8n.io is permitted (proxy/firewall)."],"exampleFix":"// before: single throw on any non-OK\nconst data = await fetchTemplateList(query);\n// after: retry with backoff for transient statuses\nasync function fetchWithRetry(query, attempts = 3) {\n  for (let i = 0; i < attempts; i++) {\n    try { return await fetchTemplateList(query); }\n    catch (e) {\n      if (i === attempts - 1) throw e;\n      await new Promise(r => setTimeout(r, 2 ** i * 500));\n    }\n  }\n}","handlingStrategy":"retry","validationCode":"// Validate query shape and retry only on transient statuses.\nfunction isLikelyTransient(status: number): boolean {\n  return status === 429 || status >= 500;\n}","typeGuard":"function isTemplateFetchError(e: unknown): e is Error {\n  return e instanceof Error && /^Failed to fetch templates:/.test(e.message);\n}","tryCatchPattern":"async function fetchTemplatesWithRetry(query, attempts = 3) {\n  let lastErr: unknown;\n  for (let i = 0; i < attempts; i++) {\n    try {\n      return await fetchTemplateList(query);\n    } catch (e) {\n      lastErr = e;\n      const m = (e as Error).message;\n      const status = Number(m.match(/\\b(\\d{3})\\b/)?.[1] ?? 0);\n      if (!isLikelyTransient(status)) throw e;\n      await new Promise((r) => setTimeout(r, 2 ** i * 500));\n    }\n  }\n  throw lastErr;\n}","preventionTips":["Wrap fetchTemplateList in exponential backoff for 429/5xx responses.","Fail fast (no retry) on 4xx other than 429 — those indicate bad query parameters.","Cache template results to avoid repeated external calls within a session.","Verify network egress to api.n8n.io in restricted environments."],"tags":["templates","network","api","external","retry"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}