n8n-io/n8n · error · CannotCreateEntityIdMapError

Cannot use given entity id "${id}" because "${metadata.targe

Error message

Cannot use given entity id "${id}" because "${metadata.targetName}" contains multiple primary columns, you must provide object in following form: ${JSON.stringify(objectExample)} as an id.

What it means

Thrown by EntityMetadata.ensureEntityIdMap when you pass a scalar id (number/string) to a repository operation on an entity that has more than one primary-key column. TypeORM cannot decide which of the composite PK columns the scalar belongs to, so it refuses to build the id map and prints the exact object shape it expects (e.g. {tenantId: 1, id: 2}). The error class is CannotCreateEntityIdMapError; it triggers only when ObjectUtils.isObject(id) is false AND this.hasMultiplePrimaryKeys is true.

Source

Thrown at packages/@n8n/typeorm/src/metadata/EntityMetadata.ts:615

	 * Returns true if it contains all of them, false if at least one of them is not defined.
	 */
	hasAllPrimaryKeys(entity: ObjectLiteral): boolean {
		return this.primaryColumns.every((primaryColumn) => {
			const value = primaryColumn.getEntityValue(entity);
			return value !== null && value !== undefined;
		});
	}

	/**
	 * Ensures that given object is an entity id map.
	 * If given id is an object then it means its already id map.
	 * If given id isn't an object then it means its a value of the id column
	 * and it creates a new id map with this value and name of the primary column.
	 */
	ensureEntityIdMap(id: any): ObjectLiteral {
		if (ObjectUtils.isObject(id)) return id;

		if (this.hasMultiplePrimaryKeys) throw new CannotCreateEntityIdMapError(this, id);

		return this.primaryColumns[0].createValueMap(id);
	}

	/**
	 * Gets primary keys of the entity and returns them in a literal object.
	 * For example, for Post{ id: 1, title: "hello" } where id is primary it will return { id: 1 }
	 * For multiple primary keys it returns multiple keys in object.
	 * For primary keys inside embeds it returns complex object literal with keys in them.
	 */
	getEntityIdMap(entity: ObjectLiteral | undefined): ObjectLiteral | undefined {
		if (!entity) return undefined;

		return EntityMetadata.getValueMap(entity, this.primaryColumns, {
			skipNulls: true,
		});
	}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Pass an id-map object instead of a scalar: repo.findOne({ where: { tenantId, id } }) using the exact key names from the printed objectExample.
  2. If you intended single-column PK, audit the entity and remove the extra @PrimaryColumn so metadata.primaryColumns has length 1.
  3. Centralize id construction in a helper (buildPk(tenantId, id)) so every call site produces the correct object shape.

Example fix

// before
const user = await userRepo.findOne(5);

// after (composite PK)
const user = await userRepo.findOne({
  where: { tenantId: ctx.tenantId, id: 5 },
});
Defensive patterns

Strategy: type-guard

Validate before calling

function isCompositePk(
  target: Function | EntitySchema<any>,
  dataSource: DataSource,
): boolean {
  const meta = dataSource.getMetadata(target);
  return meta.primaryColumns.length > 1;
}

// before calling findOne(id)
if (isCompositePk(User, dataSource)) {
  return userRepo.findOne({ where: { tenantId, id } });
}
return userRepo.findOne(id);

Type guard

type ScalarId = string | number;
type IdMap = Record<string, unknown>;
function isIdMap(id: unknown): id is IdMap {
  return typeof id === 'object' && id !== null && !Array.isArray(id);
}
function asFindOptionsId(id: ScalarId | IdMap, pkColumns: string[]): IdMap {
  if (isIdMap(id)) return id;
  if (pkColumns.length !== 1) {
    throw new Error('Scalar id supplied for composite PK; pass an object keyed by ' + pkColumns.join(','));
  }
  return { [pkColumns[0]]: id };
}

Try / catch

try {
  await userRepo.findOne(id);
} catch (err) {
  if (err instanceof CannotCreateEntityIdMapError) {
    // re-issue with the printed object shape
    throw err;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling repo.findOne(5), repo.delete(5), or any method that ultimately routes a raw id through ensureEntityIdMap on an entity whose metadata.primaryColumns.length > 1. The branch `if (this.hasMultiplePrimaryKeys) throw new CannotCreateEntityIdMapError(this, id)` is hit.

Common situations: Entities with composite primary keys (multi-tenant designs using @PrimaryColumn on both tenantId and id), or junction entities promoted to full entities. Switching a single-PK entity to composite PK but forgetting to update existing findOne(id) call sites.

Related errors


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