angular/angular-cli · error · PathIsDirectoryException
Path is a directory.
Error message
Path is a directory.
What it means
The Angular DevKit virtual file system (SimpleMemoryHost) maintains a cache of path -> stats entries. When you call write() on a path that is already recorded as a directory, _write detects the existing directory entry and throws PathIsDirectoryException. The memory host treats directories and files as mutually exclusive entries, so it refuses to overwrite a directory with file content instead of silently corrupting the tree.
Source
Thrown at packages/angular_devkit/core/src/virtual-fs/host/memory.ts:159
}
});
}
} while (parent != currentPath);
}
get capabilities(): HostCapabilities {
return { synchronous: true };
}
/**
* List of protected methods that give direct access outside the observables to the cache
* and internal states.
*/
protected _write(path: Path, content: FileBuffer): void {
path = this._toAbsolute(path);
const old = this._cache.get(path);
if (old && old.isDirectory()) {
throw new PathIsDirectoryException(path);
}
// Update all directories. If we find a file we know it's an invalid write.
const fragments = split(path);
let curr: Path = normalize('/');
for (const fr of fragments) {
curr = join(curr, fr);
const maybeStats = this._cache.get(fr);
if (maybeStats) {
if (maybeStats.isFile()) {
throw new PathIsFileException(curr);
}
} else {
this._cache.set(curr, this._newDirStats());
}
}
// Create the stats.View on GitHub (pinned to bb72145f9a)
Solutions
- Fix the caller so a file path (with filename segment) is passed to write() rather than the directory path.
- Delete the directory entry first with host.delete(dirPath) before writing a file at that path, if overwriting is truly intended.
- Check with host.isDirectory(path) (or read the stats) before writing, and branch to a different target path if it is a directory.
- If the wrong entry was cached, rebuild the host or clear the offending entry and retry the operation.
Example fix
// before
host.write(normalize('src/assets'), content);
// after
const target = normalize('src/assets/logo.svg');
if (host.isDirectory(target)) {
throw new Error('Refusing to write to a directory: ' + target);
}
host.write(target, content); Defensive patterns
Strategy: validation
Validate before calling
import { normalize, Path } from '@angular-devkit/core';
function assertWritableFile(host: { exists(p: Path): boolean; isDirectory(p: Path): boolean }, p: Path): void {
const abs = normalize(p);
if (host.exists(abs) && host.isDirectory(abs)) {
throw new Error(`Cannot write to '${abs}': it is a directory`);
}
} Type guard
function isFileEntry(entry: { isDirectory(): boolean; isFile(): boolean } | undefined): entry is { isDirectory(): boolean; isFile(): boolean; content: Buffer } {
return entry !== undefined && entry.isFile();
} Try / catch
import { PathIsDirectoryException } from '@angular-devkit/core';
try {
host.write(path, buffer);
} catch (e) {
if (e instanceof PathIsDirectoryException) {
host.delete(e.path);
host.write(path, buffer);
} else {
throw e;
}
} Prevention
- Always write to full file paths including the filename segment, never to directory prefixes.
- Check isDirectory()/isFile() before every write to a path built from dynamic input.
- Keep directory paths and file paths in separate typed variables to avoid mixing them.
When it happens
Trigger: Calling host.write(dirPath, buffer) where dirPath was previously created with a directory record in the cache (e.g. via write of a path whose parent fragments created directory entries, or an explicit directory creation). In _write, `this._cache.get(path)` returns an entry whose `isDirectory()` is true, immediately throwing before any content is stored.
Common situations: Reusing a path that was intended to be a folder prefix (e.g. writing to 'src/assets' when it is an asset directory); path-building bugs that drop a filename segment so a directory path is passed to write(); schematic templates where a folder and file share a confusingly similar name; stale in-memory caches from earlier operations in the same process.
Related errors
- Path is a file.
- File does not exist.
- File already exist.
- File already exist.
- Path ${JSON.stringify(path)} must be absolute.
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/7010475b1b801aff.
Report an issue: GitHub.