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

  1. Use a real HostTree-backed Tree so beginUpdate/commitUpdate can operate on the file.
  2. Check tree.exists(recorder.path) before committing updates.
  3. 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

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


AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30). Data as JSON: /api/errors/215a2d744645c5c8. Report an issue: GitHub.