angular/angular-cli · error · FileDoesNotExistException
Path "${record instanceof UpdateRecorderBase ? record.path :
Error message
Path "${record instanceof UpdateRecorderBase ? record.path : '<unknown>'}" does not exist. What it means
commitUpdate on a NullTree always throws FileDoesNotExistException. The message uses record.path when the recorder is a standard UpdateRecorderBase, otherwise '<unknown>'. It signals a file mutation was committed through the null tree, which supports no file operations.
Source
Thrown at packages/angular_devkit/schematics/src/tree/null.ts:96
throw new FileDoesNotExistException(path);
}
readJson(path: string): JsonValue {
throw new FileDoesNotExistException(path);
}
get(_path: string) {
return null;
}
getDir(path: string): NullTreeDirEntry {
return new NullTreeDirEntry(normalize('/' + path));
}
visit(): void {}
// Change content of host files.
beginUpdate(path: string): never {
throw new FileDoesNotExistException(path);
}
commitUpdate(record: UpdateRecorder): never {
throw new FileDoesNotExistException(
record instanceof UpdateRecorderBase ? record.path : '<unknown>',
);
}
// Change structure of the host.
copy(path: string, _to: string): never {
throw new FileDoesNotExistException(path);
}
delete(path: string): never {
throw new FileDoesNotExistException(path);
}
create(path: string, _content: Buffer | string): never {
throw new CannotCreateFileException(path);
}
rename(path: string, _to: string): never {
throw new FileDoesNotExistException(path);
}
overwrite(path: string, _content: Buffer | string): never {View on GitHub (pinned to bb72145f9a)
Solutions
- Use a real HostTree-backed Tree so beginUpdate/commitUpdate can operate on the file.
- Check tree.exists(recorder.path) before committing updates.
- If the recorder was custom (not UpdateRecorderBase), ensure it exposes a correct path and is bound to the right tree.
Example fix
// before
tree.commitUpdate(recorder);
// after
if (!tree.exists(recorder.path)) {
throw new SchematicsException(`Cannot commit update: ${recorder.path} not found`);
}
tree.commitUpdate(recorder); Defensive patterns
Strategy: try-catch
Validate before calling
const rec = recorder as UpdateRecorderBase;
if (!rec || typeof rec.path !== 'string' || !tree.exists(rec.path)) {
throw new SchematicsException('Recorder is not bound to an existing file');
} Type guard
function isBoundRecorder(r: UpdateRecorder): r is UpdateRecorderBase {
return r instanceof UpdateRecorderBase && typeof r.path === 'string';
} Try / catch
try {
tree.commitUpdate(recorder);
} catch (e) {
if (e instanceof FileDoesNotExistException) {
throw new SchematicsException(`Commit failed: ${e.file} not found in tree`);
}
throw e;
} Prevention
- Commit only recorders created from beginUpdate on the same tree
- Ensure custom recorders extend UpdateRecorderBase with a valid path
- Never reuse recorders across trees
- Check existence before beginUpdate/commitUpdate round-trips
When it happens
Trigger: Calling tree.commitUpdate(recorder) on a NullTree; committing a recorder obtained from beginUpdate on a null tree.
Common situations: Same family as other NullTree throws: missing workspace context, stubbed/test trees, fallback to NullTree when the real host cannot be created.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Path "${path}" does not exist.
- Cannot create file "${path}".
- Tree type is not supported.
- Original tree must be returned from all rules when using "ap
- Path "${path}" does not exist.
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/215a2d744645c5c8.
Report an issue: GitHub.