{"record":{"id":"215a2d744645c5c8","repo":"angular/angular-cli","slug":"path-record-instanceof-updaterecorderbase-rec","errorCode":null,"errorMessage":"Path \"${record instanceof UpdateRecorderBase ? record.path : '<unknown>'}\" does not exist.","messagePattern":"Path \"(.+?)\" does not exist\\.","errorType":"exception","errorClass":"FileDoesNotExistException","httpStatus":null,"severity":"error","filePath":"packages/angular_devkit/schematics/src/tree/null.ts","lineNumber":96,"sourceCode":"    throw new FileDoesNotExistException(path);\n  }\n  readJson(path: string): JsonValue {\n    throw new FileDoesNotExistException(path);\n  }\n  get(_path: string) {\n    return null;\n  }\n  getDir(path: string): NullTreeDirEntry {\n    return new NullTreeDirEntry(normalize('/' + path));\n  }\n  visit(): void {}\n\n  // Change content of host files.\n  beginUpdate(path: string): never {\n    throw new FileDoesNotExistException(path);\n  }\n  commitUpdate(record: UpdateRecorder): never {\n    throw new FileDoesNotExistException(\n      record instanceof UpdateRecorderBase ? record.path : '<unknown>',\n    );\n  }\n\n  // Change structure of the host.\n  copy(path: string, _to: string): never {\n    throw new FileDoesNotExistException(path);\n  }\n  delete(path: string): never {\n    throw new FileDoesNotExistException(path);\n  }\n  create(path: string, _content: Buffer | string): never {\n    throw new CannotCreateFileException(path);\n  }\n  rename(path: string, _to: string): never {\n    throw new FileDoesNotExistException(path);\n  }\n  overwrite(path: string, _content: Buffer | string): never {","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/schematics/src/tree/null.ts#L78-L114","documentation":"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.","triggerScenarios":"Calling tree.commitUpdate(recorder) on a NullTree; committing a recorder obtained from beginUpdate on a null tree.","commonSituations":"Same family as other NullTree throws: missing workspace context, stubbed/test trees, fallback to NullTree when the real host cannot be created.","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."],"exampleFix":"// before\ntree.commitUpdate(recorder);\n// after\nif (!tree.exists(recorder.path)) {\n  throw new SchematicsException(`Cannot commit update: ${recorder.path} not found`);\n}\ntree.commitUpdate(recorder);","handlingStrategy":"try-catch","validationCode":"const rec = recorder as UpdateRecorderBase;\nif (!rec || typeof rec.path !== 'string' || !tree.exists(rec.path)) {\n  throw new SchematicsException('Recorder is not bound to an existing file');\n}","typeGuard":"function isBoundRecorder(r: UpdateRecorder): r is UpdateRecorderBase {\n  return r instanceof UpdateRecorderBase && typeof r.path === 'string';\n}","tryCatchPattern":"try {\n  tree.commitUpdate(recorder);\n} catch (e) {\n  if (e instanceof FileDoesNotExistException) {\n    throw new SchematicsException(`Commit failed: ${e.file} not found in tree`);\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["schematics","tree","file-not-found","null-tree"],"backgroundTag":"file-not-found","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}