n8n-io/n8n · error · UserError
Provider connection type cannot be changed. Create a new con
Error message
Provider connection type cannot be changed. Create a new connection instead.
What it means
Thrown by `import:credentials` storeCredential when an existing credential has `usageScope === 'instance'` (a provider connection) and the import payload sets `type` to a different value than the stored type. Instance-scope provider connections are immutable in type — you cannot morph a Slack credential into an HTTP credential by re-importing.
Source
Thrown at packages/cli/src/commands/import/credentials.ts:184
credential: Partial<CredentialsEntity>,
project: Project,
ctx: OperationContext,
) {
// UsageScope is instance-local state; imports never change it for existing credentials.
let existing: Pick<CredentialsEntity, 'id' | 'type' | 'usageScope'> | null = null;
if (credential.id) {
existing = await transactionManager.findOne(CredentialsEntity, {
where: { id: credential.id },
select: ['id', 'usageScope', 'type'],
});
if (existing) {
credential.usageScope = existing.usageScope;
if (
existing.usageScope === 'instance' &&
credential.type !== undefined &&
credential.type !== existing.type
) {
throw new UserError(
'Provider connection type cannot be changed. Create a new connection instead.',
);
}
}
}
credential.usageScope ??= 'project';
if (credential.usageScope === 'instance') {
if (
credential.isGlobal ||
credential.isResolvable ||
credential.isManaged ||
credential.resolvableAllowFallback ||
credential.resolverId
) {
throw new UserError(
'Provider connections cannot be global, managed, or dynamically resolved',
);View on GitHub (pinned to 5ac6606e81)
Solutions
- Change the import JSON's `type` to match the existing instance credential's type.
- Remove the `id` field from the import JSON so a new credential is created instead of updating.
- Delete the existing instance credential first, then import.
Example fix
// before — JSON has type: "httpBasicAuth" but DB has "slackApi"
// after — match the type, or drop the id
{ "id": "x", "type": "slackApi", "name": "..." } Defensive patterns
Strategy: validation
Validate before calling
// Before importing, confirm the existing instance credential's type matches the import payload
async function typeMatches(ds: DataSource, id: string, importType: string): Promise<boolean> {
const row = await ds.getRepository('credentials_entity').findOne({ where: { id }, select: ['type', 'usageScope'] });
return row?.usageScope !== 'instance' || row.type === importType;
}
if (!(await typeMatches(ds, credential.id, credential.type))) {
throw new Error('Type mismatch — drop the id or update the JSON type');
} Prevention
- Never reuse an existing instance credential's id with a different type in import JSON.
- Strip the `id` field when importing credentials across environments to force fresh creation.
When it happens
Trigger: Re-importing a credentials JSON file where a credential with the same ID exists as an instance credential but the JSON's `type` field differs. Common when the JSON was exported from a different credential type or hand-edited.
Common situations: Bulk re-import across environments where the credential type drifted; manual JSON edits; importing a backup that was created from a different credential and reusing the ID.
Related errors
- Provider connections cannot be global, managed, or dynamical
- Provider connection data cannot be empty
- Provider connection data must be a JSON object
- You cannot use `--userId` and `--projectId` together. Use on
- You cannot use `--include` and `--exclude` together. Use one
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/1230428b2f778f9b.
Report an issue: GitHub.