n8n-io/n8n · error · TypeORMError
Cannot load entity because only one primary key was specifie
Error message
Cannot load entity because only one primary key was specified, however entity contains multiple primary keys
What it means
RelationQueryBuilder.loadMany accepts a scalar id in .of() only when the entity has a single primary key. When ObjectUtils.isObject(of) is false and metadata.hasMultiplePrimaryKeys is true, it cannot decide which PK the scalar refers to, so it throws TypeORMError rather than guessing.
Source
Thrown at packages/@n8n/typeorm/src/query-builder/RelationQueryBuilder.ts:184
/**
* Loads a single entity (relational) from the relation.
* You can also provide id of relational entity to filter by.
*/
async loadOne<T = any>(): Promise<T | undefined> {
return this.loadMany<T>().then((results) => results[0]);
}
/**
* Loads many entities (relational) from the relation.
* You can also provide ids of relational entities to filter by.
*/
async loadMany<T = any>(): Promise<T[]> {
let of = this.expressionMap.of;
if (!ObjectUtils.isObject(of)) {
const metadata = this.expressionMap.mainAlias!.metadata;
if (metadata.hasMultiplePrimaryKeys)
throw new TypeORMError(
`Cannot load entity because only one primary key was specified, however entity contains multiple primary keys`,
);
of = metadata.primaryColumns[0].createValueMap(of);
}
return this.connection.relationLoader.load(
this.expressionMap.relationMetadata,
of,
this.queryRunner,
);
}
}
View on GitHub (pinned to 5ac6606e81)
Solutions
- Pass the full PK map: .of({ tenantId, id }).loadMany().
- If only one id is available, look up the composite map first via the entity repository.
- Add a type guard on the public helper that wraps loadMany so callers cannot pass a scalar for composite-PK entities.
Example fix
// before
await qb.relation(Membership,'roles').of(membershipId).loadMany(); // composite PK
// after
await qb.relation(Membership,'roles').of({ tenantId, membershipId }).loadMany(); Defensive patterns
Strategy: type-guard
Validate before calling
import { DataSource } from 'typeorm';
function requireCompositeOf(ds: DataSource, target: Function, of: unknown) {
const meta = ds.getMetadata(target);
if (meta.hasMultiplePrimaryKeys && (typeof of !== 'object' || of === null))
throw new Error(`Entity ${meta.targetName} has composite PK; pass .of({${meta.primaryColumns.map(c => c.propertyName).join(',')}})`);
} Type guard
function isPkMap(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null;
} Prevention
- Tag composite-PK entities in a registry and route their relation loads through a helper that requires a map.
- Document composite PKs prominently on the entity class.
When it happens
Trigger: qb.relation(...).of(42).loadMany() (or loadOne) on an entity whose @PrimaryColumn set has more than one column; passing a bare id from a route param for a composite-PK entity.
Common situations: Entity migrated to composite PKs (e.g. adding tenantId to the PK) without updating callers that pass a single id; junction-table entities that are composite by design.
Related errors
- Value to be set into the relation must be a map of relation
- Entity whose relation needs to be set is not set. Use .of me
- Set operation is only supported for many-to-one and one-to-o
- Add operation is only supported for many-to-many and one-to-
- Add operation is only supported for many-to-many and one-to-
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/9a37d65cabfdff1e.
Report an issue: GitHub.