n8n-io/n8n · error · TypeORMError
Cannot update entity because entity id is not set in the ent
Error message
Cannot update entity because entity id is not set in the entity.
What it means
ReturningResultsEntityUpdator.update throws TypeORMError when, in the no-returning-statement driver path, it needs to re-select updated rows by id but metadata.getEntityIdMap(entity) returns null/undefined — i.e. the entity object passed to .update() lacks the values for its primary column(s). This path is taken by drivers that do not support RETURNING/OUTPUT (older SQLite builds, some MySQL).
Source
Thrown at packages/@n8n/typeorm/src/query-builder/ReturningResultsEntityUpdator.ts:54
const result = Array.isArray(updateResult.raw)
? updateResult.raw[entityIndex]
: updateResult.raw;
const returningColumns = this.queryRunner.connection.driver.createGeneratedMap(
metadata,
result,
);
if (returningColumns) {
this.queryRunner.manager.merge(metadata.target as any, entity, returningColumns);
updateResult.generatedMaps.push(returningColumns);
}
} else {
// for driver which do not support returning/output statement we need to perform separate query and load what we need
const updationColumns = this.expressionMap.extraReturningColumns;
if (updationColumns.length > 0) {
// get entity id by which we will get needed data
const entityId = this.expressionMap.mainAlias!.metadata.getEntityIdMap(entity);
if (!entityId)
throw new TypeORMError(
`Cannot update entity because entity id is not set in the entity.`,
);
// execute query to get needed data
const loadedReturningColumns = (await this.queryRunner.manager
.createQueryBuilder()
.select(
metadata.primaryColumns.map(
(column) => metadata.targetName + '.' + column.propertyPath,
),
)
.addSelect(
updationColumns.map((column) => metadata.targetName + '.' + column.propertyPath),
)
.from(metadata.target, metadata.targetName)
.where(entityId)
.withDeleted()
.setOption('create-pojo') // use POJO because created object can contain default values, e.g. property = null and those properties might be overridden by merge processView on GitHub (pinned to 5ac6606e81)
Solutions
- Ensure the entity passed carries its primary-key value(s) before .update().
- Prefer the criteria form manager.update(id, partial) over the entity form so the id is explicit.
- If running on SQLite/MySQL, gate any RETURNING-dependent logic and re-select using an explicit id you control.
Example fix
// before
await manager.update(User, { name: 'x' }, { name: 'y' }); // {name:'x'} has no PK on sqlite
// after
await manager.update(User, userId, { name: 'y' }); Defensive patterns
Strategy: validation
Validate before calling
import { DataSource } from 'typeorm';
function ensureHasId(ds: DataSource, target: Function, entity: Record<string, unknown>) {
const idMap = ds.getMetadata(target).getEntityIdMap(entity);
if (!idMap) throw new Error('entity is missing primary-key value(s) for re-select after update');
} Type guard
function hasEntityId(ds: DataSource, target: Function, entity: unknown): boolean {
return !!ds.getMetadata(target).getEntityIdMap(entity as Record<string, unknown>);
} Prevention
- Prefer the criteria form manager.update(id, partial) over the entity form.
- When targeting SQLite/MySQL, assert the id is present before .update().
- Avoid passing partial DTOs straight through from PATCH endpoints.
When it happens
Trigger: Calling manager.update(target, entityWithoutId, ...) or qb.update().set(...).whereEntity(partialWithNoPk) on a driver without RETURNING; the entity was constructed from a partial DTO that omitted the id.
Common situations: Switching the test harness from Postgres (RETURNING supported) to SQLite and revealing partial entities; frontend sending a PATCH body without id that the backend forwards straight to .update.
Related errors
- Internal error. Subject ${subject.metadata.targetName} must
- Property "${propertyPath}" was not found in "${metadata.targ
- Cannot save user <${this.email}>: Provided email is invalid
- The maximum number of files that can be attached to the assi
- Wrong driver: "${driverType}" given. Supported drivers are:
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/ce7c0d44b5fba9bf.
Report an issue: GitHub.