typeorm/typeorm · error · TypeORMError
.whereEntity method can only be used on queries which update
Error message
.whereEntity method can only be used on queries which update real entity table.
What it means
Thrown by UpdateQueryBuilder.whereEntity() when the mainAlias has no entity metadata. whereEntity needs primary-key columns from real entity metadata to build the OR-IN list, so it refuses queries built from raw table-name strings or aliases without a bound entity class.
Source
Thrown at src/query-builder/UpdateQueryBuilder.ts:477
* Sets LIMIT - maximum number of rows to be selected.
*
* @param limit
*/
limit(limit?: number): this {
this.expressionMap.limit = this.validateNumericInput("limit", limit)
return this
}
/**
* Indicates if entity must be updated after update operation.
* This may produce extra query or use RETURNING / OUTPUT statement (depend on database).
* Enabled by default.
*
* @param entity
*/
whereEntity(entity: Entity | Entity[]): this {
if (!this.expressionMap.mainAlias!.hasMetadata)
throw new TypeORMError(
`.whereEntity method can only be used on queries which update real entity table.`,
)
this.expressionMap.wheres = []
const entities: Entity[] = Array.isArray(entity) ? entity : [entity]
entities.forEach((entity) => {
const entityIdMap =
this.expressionMap.mainAlias!.metadata.getEntityIdMap(entity)
if (!entityIdMap)
throw new TypeORMError(
`Provided entity does not have ids set, cannot perform operation.`,
)
this.orWhereInIds(entityIdMap)
})
this.expressionMap.whereEntities = entities
return thisView on GitHub (pinned to 04ff4daedc)
Solutions
- Build the update from a registered entity: dataSource.getRepository(MyEntity).createQueryBuilder().update().
- Ensure the entity class is in the DataSource entities list.
- For raw tables, use where() with explicit conditions instead of whereEntity().
- Verify mainAlias.target is the entity class before calling whereEntity.
Example fix
// before — string table, no metadata
await dataSource.createQueryBuilder()
.update()
.set({ views: () => 'views + 1' })
.whereEntity(post)
.execute();
// after — entity-backed builder
await dataSource.getRepository(Post).createQueryBuilder()
.update()
.set({ views: () => 'views + 1' })
.whereEntity(post)
.execute(); Defensive patterns
Strategy: validation
Validate before calling
const qb = repo.createQueryBuilder().update().set({ views: () => 'views + 1' });
if (!qb.expressionMap.mainAlias?.hasMetadata) {
throw new Error('whereEntity requires an entity-backed update builder');
}
qb.whereEntity(post); Type guard
function isEntityBacked(qb: import('typeorm').QueryBuilder<any>): boolean {
return !!qb.expressionMap.mainAlias?.hasMetadata;
} Prevention
- Build update queries from a registered entity repository.
- Avoid raw table-name string aliases for update().whereEntity().
- Register target entities in the DataSource entities array.
When it happens
Trigger: Calling qb.update().set(...).whereEntity(entity) on a builder created via createQueryBuilder('raw_table') (string) or createQueryBuilder<Dto>() without an entity target. The hasMetadata check fails and throws.
Common situations: Updating a raw/non-entity table; using a DTO generic without registering the entity; refactoring that drops the entity argument; generic update helpers that accept any alias.
Related errors
- .whereEntity method can only be used on queries which update
- Cannot get entity metadata for the given alias "${this.name}
- Upsert type "merge-into" is not supported without metadata t
- Relation with property path ${this.relationPropertyPath} in
- Cannot get entity metadata for the given alias "${this.expre
AI-assisted analysis of typeorm/typeorm@04ff4daedc (2026-08-03).
Data as JSON: /data/errors/59270c09900c910d.json.
Report an issue: GitHub.