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 this

View on GitHub (pinned to 04ff4daedc)

Solutions

  1. Build the update from a registered entity: dataSource.getRepository(MyEntity).createQueryBuilder().update().
  2. Ensure the entity class is in the DataSource entities list.
  3. For raw tables, use where() with explicit conditions instead of whereEntity().
  4. 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

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


AI-assisted analysis of typeorm/typeorm@04ff4daedc (2026-08-03). Data as JSON: /data/errors/59270c09900c910d.json. Report an issue: GitHub.