n8n-io/n8n · error · Error

no artifact handler registered for type: ${type}

Error message

no artifact handler registered for type: ${type}

What it means

Thrown by getHandler() in the artifact registry when no handler in ARTIFACT_HANDLERS matches the requested ArtifactType. The registry is a fixed array (workflow, agent, config-eval). ArtifactType is itself a closed union ('workflow' | 'agent' | 'config-eval'), so at the type level this throw is unreachable for well-typed callers; it fires when a value reaches the registry outside that union (e.g. an unvalidated JSON field, an `as` cast, or a new type added to ARTIFACT_TYPES without a handler).

Source

Thrown at packages/@n8n/instance-ai/evaluations/harness/artifacts/registry.ts:17

import { agentHandler } from './agent-handler';
import { configEvalHandler } from './config-eval-handler';
import type { ArtifactHandler } from './types';
import { workflowHandler } from './workflow-handler';
import type { ArtifactType } from '../../types';

/** All registered artifact handlers. */
export const ARTIFACT_HANDLERS: ArtifactHandler[] = [
	workflowHandler,
	agentHandler,
	configEvalHandler,
];

/** Look up a handler by artifact type. Throws for an unregistered type. */
export function getHandler(type: ArtifactType): ArtifactHandler {
	const handler = ARTIFACT_HANDLERS.find((h) => h.type === type);
	if (!handler) throw new Error(`no artifact handler registered for type: ${type}`);
	return handler;
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. If you added a type to ARTIFACT_TYPES, implement an ArtifactHandler and append it to ARTIFACT_HANDLERS in registry.ts.
  2. If the value came from JSON, route it through the Zod schema so an invalid type fails at parse, not at handler lookup.
  3. Remove any `as ArtifactType` casts and rely on schema narrowing.

Example fix

// before
export const ARTIFACT_HANDLERS: ArtifactHandler[] = [workflowHandler, agentHandler, configEvalHandler];
// new type 'credential' added to ARTIFACT_TYPES but no handler
// after
import { credentialHandler } from './credential-handler';
export const ARTIFACT_HANDLERS: ArtifactHandler[] = [
  workflowHandler,
  agentHandler,
  configEvalHandler,
  credentialHandler,
];
Defensive patterns

Strategy: type-guard

Type guard

// Narrow an artifact type to the registered set before handler lookup.
import { ARTIFACT_TYPES } from '../../types';
const REGISTERED = new Set<string>(ARTIFACT_TYPES);
function isRegisteredArtifactType(type: string): type is 'workflow' | 'agent' | 'config-eval' {
  return REGISTERED.has(type);
}
// Usage:
if (!isRegisteredArtifactType(type)) {
  throw new Error(`Unknown artifact type "${type}". Registered: ${[...REGISTERED].join(', ')}`);
}
const handler = getHandler(type);

Prevention

When it happens

Trigger: A new artifact kind is added to ARTIFACT_TYPES but no handler is appended to ARTIFACT_HANDLERS; a test-case expectation array carries a type string from unvalidated input; an `as ArtifactType` cast on a value the schema didn't actually narrow.

Common situations: Extending the eval framework with a new artifact type (e.g. 'credential') and forgetting the handler; loading a test case from JSON without running it through the Zod schema that constrains the type.

Related errors


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