n8n-io/n8n · error · Error

Invalid response format from templates API

Error message

Invalid response format from templates API

What it means

Thrown by fetchTemplateList after a successful HTTP 200 from https://api.n8n.io/api/templates/search when the JSON body fails the isTemplateSearchResponse type guard. The guard requires the body to be an object containing totalWorkflows:number and workflows:array. A 2xx response carrying an HTML error page, a maintenance banner, or a backwards-incompatible schema change will trip it.

Source

Thrown at packages/@n8n/ai-workflow-builder.ee/src/tools/web/templates.ts:86

}): Promise<TemplateSearchResponse> {
	const queryString = buildSearchQueryString(query);
	const url = `${N8N_API_BASE_URL}/templates/search${queryString ? `?${queryString}` : ''}`;

	const response = await fetch(url, {
		method: 'GET',
		headers: {
			'Content-Type': 'application/json',
			Accept: 'application/json',
		},
	});

	if (!response.ok) {
		throw new Error(`Failed to fetch templates: ${response.status} ${response.statusText}`);
	}

	const data: unknown = await response.json();
	if (!isTemplateSearchResponse(data)) {
		throw new Error('Invalid response format from templates API');
	}
	return data;
}

/**
 * Fetch a specific workflow template by ID from n8n API
 */
export async function fetchTemplateByID(id: number): Promise<TemplateFetchResponse> {
	const url = `${N8N_API_BASE_URL}/workflows/templates/${id}`;

	const response = await fetch(url, {
		method: 'GET',
		headers: {
			'Content-Type': 'application/json',
			Accept: 'application/json',
		},
	});

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Inspect the actual response body (log response.text() before parsing) to see what api.n8n.io returned.
  2. Verify the endpoint and shape against the current n8n templates API documentation.
  3. If behind a proxy, bypass it and retry to rule out response rewriting.
  4. If you maintain a mock server, ensure it returns { totalWorkflows: number, workflows: [] }.

Example fix

// before
const data: unknown = await response.json();
if (!isTemplateSearchResponse(data)) {
  throw new Error('Invalid response format from templates API');
}

// after - surface the body for diagnosis
const text = await response.text();
let data: unknown;
try { data = JSON.parse(text); } catch { throw new Error(`Templates API returned non-JSON body: ${text.slice(0, 200)}`); }
if (!isTemplateSearchResponse(data)) {
  throw new Error(`Unexpected templates API shape: ${JSON.stringify(Object.keys(data ?? {}))}`);
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate before trusting the API shape — re-use the same predicate
import { isTemplateSearchResponse } from '@/tools/web/templates';

function assertSearchResponse(raw: unknown): TemplateSearchResponse {
  if (!isTemplateSearchResponse(raw)) {
    throw new Error(`Unexpected templates API shape: ${JSON.stringify(Object.keys((raw as any) ?? {}))}`);
  }
  return raw;
}

Type guard

function isTemplateSearchResponse(data: unknown): data is TemplateSearchResponse {
  if (typeof data !== 'object' || data === null) return false;
  const obj = data as Record<string, unknown>;
  return typeof obj.totalWorkflows === 'number' && Array.isArray(obj.workflows);
}

Try / catch

try {
  const result = await fetchTemplateList(query);
  // use result
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Invalid response format from templates API')) {
    // degrade gracefully — surface 'templates unavailable' to the caller
  }
  throw e;
}

Prevention

When it happens

Trigger: GET https://api.n8n.io/api/templates/search returns 200 with a body lacking totalWorkflows or workflows (e.g. CDN serves an HTML error page, the API ships a schema change, or a caching proxy returns a stale/mismatched payload). The response.ok check at line 80 has already passed, so only shape mismatches reach this throw.

Common situations: n8n.cloud or api.n8n.io deploys a templates API schema change; a corporate proxy intercepts and rewrites the JSON; an incident returns a JSON error object instead of the search envelope; local development with a mocked API that forgets the totalWorkflows field.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/a0a370d63f5351c8. Report an issue: GitHub.