{"record":{"id":"25c45c2c2c80789a","repo":"n8n-io/n8n","slug":"removed-entity-subject-metadata-name-is-also","errorCode":null,"errorMessage":"Removed entity \"${subject.metadata.name}\" is also scheduled for update operation. Make sure you are not updating and removing same object (note that update or remove may be executed by cascade operations).","messagePattern":"Removed entity \"(.+?)\" is also scheduled for update operation\\. Make sure you are not updating and removing same object \\(note that update or remove may be executed by cascade operations\\)\\.","errorType":"exception","errorClass":"SubjectRemovedAndUpdatedError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/typeorm/src/persistence/SubjectExecutor.ts","lineNumber":186,"sourceCode":"\t\t\t// console.time(\".broadcastAfterEventsForAll\");\n\t\t\tbroadcasterResult = this.broadcastAfterEventsForAll();\n\t\t\tif (broadcasterResult.promises.length > 0) await Promise.all(broadcasterResult.promises);\n\t\t\t// console.timeEnd(\".broadcastAfterEventsForAll\");\n\t\t}\n\t\t// console.timeEnd(\"SubjectExecutor.execute\");\n\t}\n\n\t// -------------------------------------------------------------------------\n\t// Protected Methods\n\t// -------------------------------------------------------------------------\n\n\t/**\n\t * Validates all given subjects.\n\t */\n\tprotected validate() {\n\t\tthis.allSubjects.forEach((subject) => {\n\t\t\tif (subject.mustBeUpdated && subject.mustBeRemoved)\n\t\t\t\tthrow new SubjectRemovedAndUpdatedError(subject);\n\t\t});\n\t}\n\n\t/**\n\t * Performs entity re-computations - finds changed columns, re-builds insert/update/remove subjects.\n\t */\n\tprotected recompute(): void {\n\t\tnew SubjectChangedColumnsComputer().compute(this.allSubjects);\n\t\tthis.insertSubjects = this.allSubjects.filter((subject) => subject.mustBeInserted);\n\t\tthis.updateSubjects = this.allSubjects.filter((subject) => subject.mustBeUpdated);\n\t\tthis.removeSubjects = this.allSubjects.filter((subject) => subject.mustBeRemoved);\n\t\tthis.softRemoveSubjects = this.allSubjects.filter((subject) => subject.mustBeSoftRemoved);\n\t\tthis.recoverSubjects = this.allSubjects.filter((subject) => subject.mustBeRecovered);\n\t\tthis.hasExecutableOperations =\n\t\t\tthis.insertSubjects.length > 0 ||\n\t\t\tthis.updateSubjects.length > 0 ||\n\t\t\tthis.removeSubjects.length > 0 ||\n\t\t\tthis.softRemoveSubjects.length > 0 ||","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/typeorm/src/persistence/SubjectExecutor.ts#L168-L204","documentation":"Before flushing, `SubjectExecutor.validate()` checks every subject and rejects any subject flagged with both `mustBeUpdated` and `mustBeRemoved`. TypeORM cannot both update and delete the same row, and the conflict usually arises indirectly through cascade rules touching the same instance from two paths.","triggerScenarios":"A relation configured with `cascade: ['update', 'remove']` (or `cascade: true`) where the same entity is reached twice in one persistence pass — once scheduled for update (e.g. its parent was saved) and once for removal (e.g. another relation removed it). Detaching an entity from one collection while simultaneously editing it through another.","commonSituations":"Two parents share a child entity; saving parent A schedules the child for update while removing parent B schedules it for delete in the same unit of work. A @ManyToMany with cascade remove combined with a separate update of the join target.","solutions":["Split the unit of work: `await em.save(parentA)` and `await em.remove(parentB)` in separate flushes so the child is not double-scheduled.","Narrow `cascade` on the relation to only the operations you need (e.g. `cascade: ['insert', 'update']` without 'remove').","Detach the shared entity from one relation before persisting so it is not simultaneously updated and removed."],"exampleFix":"// before — one flush updates and removes the same child\nawait dataSource.manager.save([parentA]);   // schedules child update\nawait dataSource.manager.remove([parentB]); // schedules child remove (same flush)\n\n// after — separate flushes\nawait dataSource.manager.save([parentA]);\nawait dataSource.manager.remove([parentB]);","handlingStrategy":"validation","validationCode":"// Before flushing, ensure no entity is referenced by both an update and a remove path\n// (simple heuristic for a single manager scope): track ids you save vs remove\nconst savedIds = new Set<string>();\nconst removedIds = new Set<string>();\nconst key = (meta, e) => `${meta.name}#${meta.primaryColumns.map(c => c.getEntityValue(e)).join(':')}`;\n// call before remove: if (savedIds.has(key(...))) throw 'subject both updated and removed';","typeGuard":null,"tryCatchPattern":"try { await dataSource.manager.save(entities); } catch (e) { if (e instanceof SubjectRemovedAndUpdatedError) { /* split into separate flushes / narrow cascade */ } throw e; }","preventionTips":["Avoid `cascade: true`; enumerate the cascade operations you actually need.","Do not edit and remove the same entity within one unit of work — flush in between.","Detach shared children from a relation before removing its parent."],"tags":["typeorm","persistence","cascade","unit-of-work","conflict"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}