n8n-io/n8n · error · UserError

File does not seem to contain credentials. Make sure the cre

Error message

File does not seem to contain credentials. Make sure the credentials are contained in an array.

What it means

Thrown by readCredentials when not using `--separate`: the JSON file parsed but is not an array. The single-file credential import format requires an array of credential objects, even for a single credential.

Source

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

		let credentials: Array<Partial<CredentialsEntity>>;

		if (separate) {
			const files = await glob('*.json', {
				cwd: inputPath,
				absolute: true,
			});

			credentials = files.map((file) =>
				jsonParse<Partial<CredentialsEntity>>(fs.readFileSync(file, { encoding: 'utf8' })),
			);
		} else {
			const credentialsUnchecked = jsonParse<Array<Partial<CredentialsEntity>>>(
				fs.readFileSync(inputPath, { encoding: 'utf8' }),
			);

			if (!Array.isArray(credentialsUnchecked)) {
				throw new UserError(
					'File does not seem to contain credentials. Make sure the credentials are contained in an array.',
				);
			}

			credentials = credentialsUnchecked;
		}

		const knownProperties = new Set(credentials.flatMap((credential) => Object.keys(credential)));
		this.warnOnUnknownProperties(include, knownProperties, '--include');
		this.warnOnUnknownProperties(exclude, knownProperties, '--exclude');

		return await Promise.all(
			credentials.map(async (credential) => {
				const filteredCredential = this.filterCredentialProperties(credential, include, exclude);
				if (isCredentialData(filteredCredential.data)) {
					// plain data / decrypted input. Should be encrypted first.
					filteredCredential.data = await cipher.encryptV2(filteredCredential.data);
				}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Wrap the credential object in an array: `[{ ... }]`.
  2. Alternatively use `--separate --input=dir/` where each file is one credential object.

Example fix

// before — f.json
{ "id": "x", "name": "..." }
// after — f.json
[ { "id": "x", "name": "..." } ]
Defensive patterns

Strategy: type-guard

Validate before calling

function parseCredentialsFile(raw: string): Array<Partial<CredentialsEntity>> {
  const parsed = JSON.parse(raw);
  if (!Array.isArray(parsed)) {
    throw new Error('Credentials file must contain a JSON array');
  }
  return parsed;
}

Type guard

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

Prevention

When it happens

Trigger: `n8n import:credentials --input=f.json` where f.json contains a bare object `{...}` instead of `[{...}]`, or a non-credential JSON structure.

Common situations: Hand-editing an export down to a single object and forgetting the brackets; pulling a credential from an API that returns an object; using a workflow export file by mistake.

Related errors


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