n8n-io/n8n · error · UserError

Provider connection data must be a JSON object

Error message

Provider connection data must be a JSON object

What it means

Thrown by validateInstanceCredentialData after decrypting the credential data: the decrypted payload is not a plain JSON object. isCredentialData (credentials.ts:69-70) requires `typeof === 'object'`, non-null, and not an array. So arrays, strings, numbers, booleans all fail.

Source

Thrown at packages/cli/src/commands/import/credentials.ts:266

		if (data === undefined && credential.id) {
			data = (
				await transactionManager.findOne(CredentialsEntity, {
					where: { id: credential.id },
					select: { data: true },
				})
			)?.data;
		}
		if (data === undefined) return;
		if (data === null || data === '') {
			throw new UserError('Provider connection data cannot be empty');
		}

		const decrypted =
			typeof data === 'string'
				? jsonParse<unknown>(await Container.get(Cipher).decryptV2(data))
				: data;
		if (!isCredentialData(decrypted)) {
			throw new UserError('Provider connection data must be a JSON object');
		}
		const credentialsService = Container.get(CredentialsService);
		if (existing?.usageScope === 'instance') {
			await credentialsService.validateInstanceCredentialUpdate(
				existing,
				decrypted,
				undefined,
				ctx,
			);
		} else {
			credentialsService.validateInstanceCredentialData(decrypted);
		}
	}

	private async checkRelations(
		transactionManager: EntityManager,
		credentials: Array<Pick<Partial<CredentialsEntity>, 'id'>>,
		projectId?: string,

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Ensure the instance credential's `data` is a JSON object literal: `{ "...": "..." }`.
  2. If using encrypted data, confirm the encryption key matches the one that encrypted it (otherwise decryption yields garbage).

Example fix

// before
{ "usageScope": "instance", "data": ["a","b"] }
// after
{ "usageScope": "instance", "data": { "values": ["a","b"] } }
Defensive patterns

Strategy: type-guard

Validate before calling

const isPlainObject = (v: unknown): v is Record<string, unknown> =>
  typeof v === 'object' && v !== null && !Array.isArray(v);

function validateInstanceCredentialData(c: Partial<CredentialsEntity>) {
  if (c.usageScope === 'instance' && c.data !== undefined && !isPlainObject(c.data)) {
    throw new Error('Instance credential data must be a plain JSON object');
  }
}
validateInstanceCredentialData(credential);

Type guard

const isCredentialData = (data: unknown): data is Record<string, unknown> =>
  typeof data === 'object' && data !== null && !Array.isArray(data);

Prevention

When it happens

Trigger: Import JSON where the (decrypted) `data` is a JSON array, a raw string, a number, or a boolean — e.g. `data: ["a","b"]` or `data: "key"`. Also fires if the encrypted string decrypts to a non-object payload.

Common situations: Mis-formatted credential export; credential data hand-crafted as an array; encryption/decryption key mismatch producing garbage that JSON-parses to a non-object.

Related errors


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