n8n-io/n8n · error · SubjectRemovedAndUpdatedError
Removed entity "${subject.metadata.name}" is also scheduled
Error message
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). What it means
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.
Source
Thrown at packages/@n8n/typeorm/src/persistence/SubjectExecutor.ts:186
// console.time(".broadcastAfterEventsForAll");
broadcasterResult = this.broadcastAfterEventsForAll();
if (broadcasterResult.promises.length > 0) await Promise.all(broadcasterResult.promises);
// console.timeEnd(".broadcastAfterEventsForAll");
}
// console.timeEnd("SubjectExecutor.execute");
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------
/**
* Validates all given subjects.
*/
protected validate() {
this.allSubjects.forEach((subject) => {
if (subject.mustBeUpdated && subject.mustBeRemoved)
throw new SubjectRemovedAndUpdatedError(subject);
});
}
/**
* Performs entity re-computations - finds changed columns, re-builds insert/update/remove subjects.
*/
protected recompute(): void {
new SubjectChangedColumnsComputer().compute(this.allSubjects);
this.insertSubjects = this.allSubjects.filter((subject) => subject.mustBeInserted);
this.updateSubjects = this.allSubjects.filter((subject) => subject.mustBeUpdated);
this.removeSubjects = this.allSubjects.filter((subject) => subject.mustBeRemoved);
this.softRemoveSubjects = this.allSubjects.filter((subject) => subject.mustBeSoftRemoved);
this.recoverSubjects = this.allSubjects.filter((subject) => subject.mustBeRecovered);
this.hasExecutableOperations =
this.insertSubjects.length > 0 ||
this.updateSubjects.length > 0 ||
this.removeSubjects.length > 0 ||
this.softRemoveSubjects.length > 0 ||View on GitHub (pinned to 5ac6606e81)
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.
Example fix
// before — one flush updates and removes the same child await dataSource.manager.save([parentA]); // schedules child update await dataSource.manager.remove([parentB]); // schedules child remove (same flush) // after — separate flushes await dataSource.manager.save([parentA]); await dataSource.manager.remove([parentB]);
Defensive patterns
Strategy: validation
Validate before calling
// Before flushing, ensure no entity is referenced by both an update and a remove path
// (simple heuristic for a single manager scope): track ids you save vs remove
const savedIds = new Set<string>();
const removedIds = new Set<string>();
const key = (meta, e) => `${meta.name}#${meta.primaryColumns.map(c => c.getEntityValue(e)).join(':')}`;
// call before remove: if (savedIds.has(key(...))) throw 'subject both updated and removed'; Try / catch
try { await dataSource.manager.save(entities); } catch (e) { if (e instanceof SubjectRemovedAndUpdatedError) { /* split into separate flushes / narrow cascade */ } throw e; } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Relation ${entityMetadata.name}#${relation.propertyName} and
- Cannot ${operation}, given value must be instance of entity
- Internal error. Subject ${subject.metadata.targetName} must
- Cyclic dependency: ${JSON.stringify(node)}
- Found unknown node. Make sure to provided all involved nodes
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/25c45c2c2c80789a.
Report an issue: GitHub.