n8n-io/n8n · error · Error

No serializer registered for format '${format}'. Provide a r

Error message

No serializer registered for format '${format}'. Provide a registry with serializers when creating the workflow.

What it means

toFormat(format) serializes a built workflow using a plugin registry. The registry is optional — it is only attached when the workflow is created via createWorkflow with a WorkflowBuilderOptions carrying a registry, or when default plugins register serializers. If the builder instance has no registry at all, toFormat() cannot proceed and throws this error pointing the caller to supply a registry at construction time.

Source

Thrown at packages/@n8n/workflow-sdk/src/workflow-builder.ts:765

						issue.nodeName,
						issue.parameterPath,
						issue.originalName,
						issue.violationLevel,
						issue.severity === 'informational' ? 'informational' : 'warning',
					),
				);
			}
		}
	}

	toString(): string {
		return JSON.stringify(this.toJSON(), null, 2);
	}

	toFormat<T>(format: string): T {
		const registry = this._registry;
		if (!registry) {
			throw new Error(
				`No serializer registered for format '${format}'. Provide a registry with serializers when creating the workflow.`,
			);
		}
		const serializer = registry.getSerializer(format);
		if (!serializer) {
			throw new Error(`No serializer registered for format '${format}'`);
		}

		const ctx: SerializerContext = {
			nodes: this._nodes,
			workflowId: this.id,
			workflowName: this.name,
			settings: this._settings,
			pinData: this._pinData,
			meta: this._meta,
			resolveTargetNodeName: (target: unknown) => this.resolveTargetNodeName(target),
		};

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Create the workflow via the workflow() factory and pass { registry: myRegistry } as the options argument.
  2. If using fromJSON(), the imported builder has no registry — use .toJSON() instead, or re-create via workflow() with a registry to use toFormat().
  3. Ensure registerDefaultPlugins has run (it runs on module load) so the default jsonSerializer is available through the global pluginRegistry.

Example fix

// before
const wf = workflow.fromJSON(json);
wf.toFormat('json'); // throws — no registry

// after
const wf = workflow('id', 'name', { registry: pluginRegistry });
wf.add(trigger({})).to(node({ type: 'Set' }));
wf.toFormat('json');
Defensive patterns

Strategy: validation

Validate before calling

import { pluginRegistry } from 'workflow-sdk';

function hasRegistry(wf: any): boolean {
  return wf._registry != null; // or expose a public getter
}
if (!hasRegistry(wf)) {
  // re-create with a registry, or use toJSON() instead of toFormat()
}

Type guard

function hasRegistry(wf: { toFormat(format: string): unknown }): boolean {
  // Probe by checking the public surface; the cleanest check is whether
  // the workflow was created via workflow() with a registry option.
  return Boolean((wf as any)._registry);
}

Try / catch

try {
  return wf.toFormat('json');
} catch (e) {
  if (e instanceof Error && /No serializer registered/.test(e.message)) {
    return wf.toJSON(); // fall back to plain JSON
  }
  throw e;
}

Prevention

When it happens

Trigger: Constructing a WorkflowBuilderImpl directly without a registry (or via a path that omits the registry argument), then calling .toFormat('json') or any other format. Also when fromJSON() creates a builder — it passes undefined as the registry.

Common situations: Using the lower-level WorkflowBuilderImpl constructor directly instead of the workflow() factory; importing a workflow via fromJSON() and then trying toFormat(); custom integrations that build the impl manually.

Related errors


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