{"record":{"id":"bbda38e7b62d40f1","repo":"angular/angular-cli","slug":"path-is-a-file","errorCode":null,"errorMessage":"Path is a file.","messagePattern":"Path is a file\\.","errorType":"exception","errorClass":"PathIsFileException","httpStatus":null,"severity":"error","filePath":"packages/angular_devkit/core/src/virtual-fs/host/memory.ts","lineNumber":170,"sourceCode":"   * List of protected methods that give direct access outside the observables to the cache\n   * and internal states.\n   */\n  protected _write(path: Path, content: FileBuffer): void {\n    path = this._toAbsolute(path);\n    const old = this._cache.get(path);\n    if (old && old.isDirectory()) {\n      throw new PathIsDirectoryException(path);\n    }\n\n    // Update all directories. If we find a file we know it's an invalid write.\n    const fragments = split(path);\n    let curr: Path = normalize('/');\n    for (const fr of fragments) {\n      curr = join(curr, fr);\n      const maybeStats = this._cache.get(fr);\n      if (maybeStats) {\n        if (maybeStats.isFile()) {\n          throw new PathIsFileException(curr);\n        }\n      } else {\n        this._cache.set(curr, this._newDirStats());\n      }\n    }\n\n    // Create the stats.\n    const stats: Stats<SimpleMemoryHostStats> = this._newFileStats(content, old);\n    this._cache.set(path, stats);\n    this._updateWatchers(path, old ? HostWatchEventType.Changed : HostWatchEventType.Created);\n  }\n  protected _read(path: Path): FileBuffer {\n    path = this._toAbsolute(path);\n    const maybeStats = this._cache.get(path);\n    if (!maybeStats) {\n      throw new FileDoesNotExistException(path);\n    } else if (maybeStats.isDirectory()) {\n      throw new PathIsDirectoryException(path);","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/core/src/virtual-fs/host/memory.ts#L152-L188","documentation":"During _write, after handling the target itself, the memory host walks every fragment of the path from the root to ensure each intermediate segment is a directory. If any fragment lookup hits an existing FILE entry (`maybeStats.isFile()`), it throws PathIsFileException because a file cannot act as a parent directory. This keeps the in-memory tree structurally valid.","triggerScenarios":"Calling host.write('some/existingfile.txt/child.txt', content) — the fragment 'existingfile.txt' exists in the cache as a file, so creating 'child.txt' under it throws. Also triggered when a prior write created a file whose name now collides with a directory component of a deeper path.","commonSituations":"Joining paths from user input or config where a filename accidentally becomes a folder (e.g. baseDir already contains a filename); path concat bugs with template strings ('path' + file) missing a separator; case where a schematic generated 'foo' as a file earlier and later writes 'foo/bar'.","solutions":["Fix the constructed path so no intermediate segment is an existing file; inspect each fragment with host.exists()/host.isFile().","Rename or delete the conflicting file entry if it is no longer needed, then retry the write.","Use a different output location to avoid a file name doubling as a directory name.","Normalize/validate user-supplied or config-supplied paths before passing them to write()."],"exampleFix":"// before\nhost.write(join(basePath, 'README.md', 'intro.txt'), content); // README.md is a file\n// after\nconst target = join(basePath, 'docs', 'intro.txt');\nhost.write(target, content);","handlingStrategy":"validation","validationCode":"import { join, normalize, Path, split } from '@angular-devkit/core';\n\nfunction assertValidFilePath(host: { exists(p: Path): boolean; isFile(p: Path): boolean }, filePath: Path): void {\n  let curr: Path = normalize('/');\n  for (const fr of split(normalize(filePath))) {\n    curr = join(curr, fr);\n    if (host.exists(curr) && host.isFile(curr) && curr !== normalize(filePath)) {\n      throw new Error(`'${curr}' is a file but is used as a directory in path '${filePath}'`);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"import { PathIsFileException } from '@angular-devkit/core';\n\ntry {\n  host.write(path, buffer);\n} catch (e) {\n  if (e instanceof PathIsFileException) {\n    throw new Error(`Fix path construction: '${e.path}' collides with an existing file`);\n  }\n  throw e;\n}","preventionTips":["Validate user/config-provided base paths to ensure they are directories, not files.","Join paths with the library's join() instead of string concatenation to avoid missing separators.","Before creating deep paths, verify no intermediate segment name is already registered as a file."],"tags":["virtual-fs","file-system","angular-devkit","path"],"backgroundTag":"path-is-a-file","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}