n8n-io/n8n · error · Error

Invalid model ID "${rawId}": expected "provider/model-name"

Error message

Invalid model ID "${rawId}": expected "provider/model-name" format

What it means

`createModel` requires the model ID in `"provider/model-name"` format — the slash separates the provider key from the model name. It throws when there is no slash (`slashIndex === -1`) or the slash is at position 0 (`slashIndex <= 0`), meaning the provider portion is empty. Both the provider segment and the model-name segment must be non-empty.

Source

Thrown at packages/@n8n/agents/src/runtime/model/model-factory.ts:232

const SUPPORTED_PROVIDERS = Object.keys(LANGUAGE_PROVIDERS).join(', ');

/**
 * Provider packages are loaded dynamically via require() so only the
 * provider needed at runtime must be installed.
 */
export function createModel(config: ModelConfig, fetch?: FetchFn): LanguageModel {
	if (isLanguageModel(config)) {
		return config;
	}

	const rawId = typeof config === 'string' ? config : config.id;
	if (!rawId || rawId.trim() === '') {
		throw new Error('Model ID is required');
	}

	const slashIndex = rawId.indexOf('/');
	if (slashIndex <= 0) {
		throw new Error(`Invalid model ID "${rawId}": expected "provider/model-name" format`);
	}
	const provider = rawId.slice(0, slashIndex) as ProviderId;
	const modelName = rawId.slice(slashIndex + 1);

	const entry = LANGUAGE_PROVIDERS[provider];
	if (!entry) {
		throw new Error(
			`Unsupported provider: "${provider}". Supported providers: ${SUPPORTED_PROVIDERS}`,
		);
	}

	// Collect credential fields: strip `id`, pass the rest to Zod validation.
	let credFields: Record<string, unknown> = {};
	if (typeof config !== 'string') {
		const { id: _id, ...rest } = config as { id: string; [k: string]: unknown };
		credFields = rest;
	}
	// Host configs (e.g. Instance AI's `{ id, url }` for OpenAI-compatible

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Check the raw model ID string — it must contain a `/` with a non-empty provider before it.
  2. Prefix the model name with the correct provider: `openai/gpt-4o`, `anthropic/claude-sonnet-4-5`, `google/gemini-1.5-pro`, etc.
  3. Add input validation in the config/UI layer to enforce the `provider/model` format with a regex before saving.
  4. If migrating from a bare-name config, write a migration that maps known model names to their `provider/name` form.

Example fix

// before:
createModel('claude-sonnet-4-5');

// after:
createModel('anthropic/claude-sonnet-4-5');
Defensive patterns

Strategy: validation

Validate before calling

const MODEL_ID_PATTERN = /^[a-zA-Z0-9-]+\/.+$/;

function validateModelIdFormat(id: string): void {
  if (!MODEL_ID_PATTERN.test(id)) {
    throw new Error(`Model ID "${id}" must be in "provider/model-name" format`);
  }
}

validateModelIdFormat(config.modelId);
const model = createModel(config.modelId);

Type guard

function isProviderModelFormat(id: string): boolean {
  const slashIndex = id.indexOf('/');
  return slashIndex > 0 && slashIndex < id.length - 1;
}

Prevention

When it happens

Trigger: Calling `createModel('claude-sonnet-4-5')` (no provider prefix), `createModel('/gpt-4o')` (empty provider), or `createModel({ id: 'gpt-4o' })`. Any ID lacking a `provider/` prefix triggers this.

Common situations: The user entered a bare model name without the provider prefix. A config migration stripped the provider segment. The model field in a UI accepted a bare name. Confusion between OpenAI-style model names (`gpt-4o`) and the required `openai/gpt-4o` format.

Related errors


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