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

  1. Fix the caller so a file path (with filename segment) is passed to write() rather than the directory path.
  2. Delete the directory entry first with host.delete(dirPath) before writing a file at that path, if overwriting is truly intended.
  3. Check with host.isDirectory(path) (or read the stats) before writing, and branch to a different target path if it is a directory.
  4. 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

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


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