n8n-io/n8n · error · Error

Invalid credentials for provider "${provider}": ${issues}

Error message

Invalid credentials for provider "${provider}":
${issues}

What it means

After resolving the provider, `createModel` passes the credential fields (everything except `id`) through a Zod schema specific to that provider (`PROVIDER_CREDENTIAL_SCHEMAS[provider]`). If validation fails, it formats the Zod issues (path + message per issue) and throws. This catches missing required fields, wrong types, and invalid formats in the credential object.

Source

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

		credFields = rest;
	}
	// Host configs (e.g. Instance AI's `{ id, url }` for OpenAI-compatible
	// endpoints) spell the base URL as `url`; the provider schemas only know
	// `baseURL`, and Zod strips unknown keys, so normalize before validation.
	// An EMPTY url means "no custom endpoint" (Instance AI emits `url: ''` for
	// the api-key-only config) and must keep the provider default.
	if (typeof credFields.url === 'string' && credFields.baseURL === undefined) {
		const { url, ...restCreds } = credFields;
		credFields = url ? { ...restCreds, baseURL: url } : restCreds;
	}

	const schema = PROVIDER_CREDENTIAL_SCHEMAS[provider];
	const parsed = schema.safeParse(credFields);
	if (!parsed.success) {
		const issues = parsed.error.issues
			.map((i) => `  - ${i.path.join('.')}: ${i.message}`)
			.join('\n');
		throw new Error(`Invalid credentials for provider "${provider}":\n${issues}`);
	}

	// Caller-injected transport wins; fall back to the ambient env-proxy resolver.
	const resolvedFetch = fetch ?? getProxyFetch();
	// Type cast: the registry guarantees the schema and builder are aligned per provider.
	return (entry.build as EntryBuilder<typeof provider>)(
		parsed.data as never,
		modelName,
		resolvedFetch,
	);
}

/**
 * Registry of embedding provider packages and their factory function names.
 * Each AI SDK provider follows the same pattern:
 *   createProvider({ apiKey }).embeddingModel(modelName)
 *
 * To add a new provider, install its @ai-sdk/* package and add an entry here.

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Read the formatted issues in the error message — each line names the field path and what Zod requires.
  2. Provide the missing or corrected credential fields in the config object passed to `createModel`.
  3. Verify the credential type matches the provider (Anthropic credential for `anthropic/`, Bedrock credential for `aws-bedrock/`, etc.).
  4. Check the credential resolution pipeline — ensure decryption/lookup actually populates every field the provider schema requires.

Example fix

// before:
createModel({ id: 'aws-bedrock/claude-3-opus', apiKey: 'xxx' });
// Error: Bedrock schema requires region, accessKeyId, secretAccessKey

// after:
createModel({
  id: 'aws-bedrock/claude-3-opus',
  region: 'us-east-1',
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
});
Defensive patterns

Strategy: validation

Validate before calling

import { PROVIDER_CREDENTIAL_SCHEMAS, type ProviderId } from './provider-credentials';

function validateCredentials(provider: ProviderId, creds: Record<string, unknown>): void {
  const schema = PROVIDER_CREDENTIAL_SCHEMAS[provider];
  const result = schema.safeParse(creds);
  if (!result.success) {
    throw new Error(`Credential validation failed for ${provider}: ${result.error.message}`);
  }
}

// Before createModel:
validateCredentials(provider, credFields);

Try / catch

try {
  const model = createModel(config);
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Invalid credentials')) {
    // Show credential configuration error to user
    logger.error('Model credential validation failed', { issues: e.message });
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing `createModel({ id: 'anthropic/claude-sonnet-4-5' })` with no API key when the Anthropic schema requires one. Passing `createModel({ id: 'aws-bedrock/claude', apiKey: '...' })` when Bedrock requires `region`, `accessKeyId`, `secretAccessKey`. Passing a malformed URL for `baseURL`.

Common situations: The credential resolution layer (e.g. n8n credential decryption) returned an incomplete or empty object. The wrong credential type was bound to the provider (e.g. OpenAI credential for a Bedrock model). A required field like `apiVersion` for Azure was omitted. Environment variables for the credential were not set.

Understand the failure class

Related errors


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