{"record":{"id":"ce7c0d44b5fba9bf","repo":"n8n-io/n8n","slug":"cannot-update-entity-because-entity-id-is-not-set","errorCode":null,"errorMessage":"Cannot update entity because entity id is not set in the entity.","messagePattern":"Cannot update entity because entity id is not set in the entity\\.","errorType":"exception","errorClass":"TypeORMError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/query-builder/ReturningResultsEntityUpdator.ts","lineNumber":54,"sourceCode":"\t\t\t\t\tconst result = Array.isArray(updateResult.raw)\n\t\t\t\t\t\t? updateResult.raw[entityIndex]\n\t\t\t\t\t\t: updateResult.raw;\n\t\t\t\t\tconst returningColumns = this.queryRunner.connection.driver.createGeneratedMap(\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\tresult,\n\t\t\t\t\t);\n\t\t\t\t\tif (returningColumns) {\n\t\t\t\t\t\tthis.queryRunner.manager.merge(metadata.target as any, entity, returningColumns);\n\t\t\t\t\t\tupdateResult.generatedMaps.push(returningColumns);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// for driver which do not support returning/output statement we need to perform separate query and load what we need\n\t\t\t\t\tconst updationColumns = this.expressionMap.extraReturningColumns;\n\t\t\t\t\tif (updationColumns.length > 0) {\n\t\t\t\t\t\t// get entity id by which we will get needed data\n\t\t\t\t\t\tconst entityId = this.expressionMap.mainAlias!.metadata.getEntityIdMap(entity);\n\t\t\t\t\t\tif (!entityId)\n\t\t\t\t\t\t\tthrow new TypeORMError(\n\t\t\t\t\t\t\t\t`Cannot update entity because entity id is not set in the entity.`,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// execute query to get needed data\n\t\t\t\t\t\tconst loadedReturningColumns = (await this.queryRunner.manager\n\t\t\t\t\t\t\t.createQueryBuilder()\n\t\t\t\t\t\t\t.select(\n\t\t\t\t\t\t\t\tmetadata.primaryColumns.map(\n\t\t\t\t\t\t\t\t\t(column) => metadata.targetName + '.' + column.propertyPath,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.addSelect(\n\t\t\t\t\t\t\t\tupdationColumns.map((column) => metadata.targetName + '.' + column.propertyPath),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.from(metadata.target, metadata.targetName)\n\t\t\t\t\t\t\t.where(entityId)\n\t\t\t\t\t\t\t.withDeleted()\n\t\t\t\t\t\t\t.setOption('create-pojo') // use POJO because created object can contain default values, e.g. property = null and those properties might be overridden by merge process","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/query-builder/ReturningResultsEntityUpdator.ts#L36-L72","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait manager.update(User, { name: 'x' }, { name: 'y' }); // {name:'x'} has no PK on sqlite\n// after\nawait manager.update(User, userId, { name: 'y' });","handlingStrategy":"validation","validationCode":"import { DataSource } from 'typeorm';\n\nfunction ensureHasId(ds: DataSource, target: Function, entity: Record<string, unknown>) {\n  const idMap = ds.getMetadata(target).getEntityIdMap(entity);\n  if (!idMap) throw new Error('entity is missing primary-key value(s) for re-select after update');\n}","typeGuard":"function hasEntityId(ds: DataSource, target: Function, entity: unknown): boolean {\n  return !!ds.getMetadata(target).getEntityIdMap(entity as Record<string, unknown>);\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["typeorm","returning-updator","update","primary-key","driver-sqlite"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}