angular/angular-cli · error · MergeConflictException
A merge conflicted on path "${path}".
Error message
A merge conflicted on path "${path}". What it means
MergeConflictException from HostTree.merge is thrown when merging a tree whose actions include a Create ('c') for a path that already exists in the target tree, unless creationConflictAllowed was set. Two trees both creating the same file is treated as a conflict because the sink would reject the second create anyway.
Source
Thrown at packages/angular_devkit/schematics/src/tree/host-tree.ts:211
const overwriteConflictAllowed =
(strategy & MergeStrategy.AllowOverwriteConflict) == MergeStrategy.AllowOverwriteConflict;
const deleteConflictAllowed =
(strategy & MergeStrategy.AllowDeleteConflict) == MergeStrategy.AllowDeleteConflict;
other.actions.forEach((action) => {
switch (action.kind) {
case 'c': {
const { path, content } = action;
if (this._willCreate(path) || this._willOverwrite(path) || this.exists(path)) {
const existingContent = this.read(path);
if (existingContent && content.equals(existingContent)) {
// Identical outcome; no action required
return;
}
if (!creationConflictAllowed) {
throw new MergeConflictException(path);
}
this._record.overwrite(path, content as {} as virtualFs.FileBuffer).subscribe();
} else {
this._record.create(path, content as {} as virtualFs.FileBuffer).subscribe();
}
return;
}
case 'o': {
const { path, content } = action;
if (this._willDelete(path) && !overwriteConflictAllowed) {
throw new MergeConflictException(path);
}
// Ignore if content is the same (considered the same change).
if (this._willOverwrite(path)) {View on GitHub (pinned to bb72145f9a)
Solutions
- Pass { creationConflictAllowed: true } to merge() if overwriting the existing file is intended.
- Ensure only one tree creates the file; convert the second side to an overwrite action.
- Stagger or namespace generated file paths so the two trees create different files.
- Delete the pre-existing file from the target tree before merging.
Example fix
// before
host.merge(other); // throws on duplicate creates
// after
host.merge(other, { creationConflictAllowed: true }); Defensive patterns
Strategy: try-catch
Validate before calling
const conflicts: string[] = [];
other.actions.forEach((a) => { if (a.kind === 'c' && tree.exists(a.path)) conflicts.push(a.path); });
if (conflicts.length) { /* resolve or set creationConflictAllowed */ } Type guard
null
Try / catch
try { host.merge(other); } catch (e) { if (e instanceof MergeConflictException) { host.merge(other, { creationConflictAllowed: true }); } else { throw e; } } Prevention
- Namespace generated file paths to avoid cross-schematic collisions
- Audit merge() inputs with tree.actions before merging
- Decide explicitly on conflict-allowance flags per merge
When it happens
Trigger: tree.merge(other) or branch merging where `other` contains a create action for a path already present in `this`, and options.creationConflictAllowed is not true.
Common situations: Composing schematics that each generate the same new file (e.g. both add a README or config); applying a partial schematic to a tree that already staged the same file; re-running generation into a branched tree.
Related errors
- Tree type is not supported.
- Original tree must be returned from all rules when using "ap
- Path "${record instanceof UpdateRecorderBase ? record.path :
- Cannot create file "${path}".
- Tree type is not supported.
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/b2759e5afdc3c62f.
Report an issue: GitHub.