angular/angular-cli · error · FileAlreadyExistException

File already exist.

Error message

File already exist.

What it means

After confirming the source exists, _rename checks the destination: if `this._cache.has(to)` is true it throws FileAlreadyExistException. The memory host never silently overwrites an existing entry on rename, forcing callers to resolve collisions explicitly.

Source

Thrown at packages/angular_devkit/core/src/virtual-fs/host/memory.ts:214

    path = this._toAbsolute(path);
    if (this._isDirectory(path)) {
      for (const [cachePath] of this._cache.entries()) {
        if (cachePath.startsWith(path + NormalizedSep) || cachePath === path) {
          this._cache.delete(cachePath);
        }
      }
    } else {
      this._cache.delete(path);
    }
    this._updateWatchers(path, HostWatchEventType.Deleted);
  }
  protected _rename(from: Path, to: Path): void {
    from = this._toAbsolute(from);
    to = this._toAbsolute(to);
    if (!this._cache.has(from)) {
      throw new FileDoesNotExistException(from);
    } else if (this._cache.has(to)) {
      throw new FileAlreadyExistException(to);
    }

    if (this._isDirectory(from)) {
      for (const path of this._cache.keys()) {
        if (path.startsWith(from + NormalizedSep)) {
          const content = this._cache.get(path);
          if (content) {
            // We don't need to clone or extract the content, since we're moving files.
            this._cache.set(join(to, NormalizedSep, path.slice(from.length)), content);
          }
        }
      }
    } else {
      const content = this._cache.get(from);
      if (content) {
        const fragments = split(to);
        const newDirectories: Path[] = [];
        let curr: Path = normalize('/');

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Delete the existing destination first (host.delete(to)) if overwriting is intended, then rename.
  2. Rename the destination to a backup path before the move, or pick a unique destination name (suffix/timestamp).
  3. Check host.exists(to) beforehand and branch: skip, overwrite, or generate an alternate name.
  4. Make the operation idempotent by tracking completed renames so reruns don't collide.

Example fix

// before
host.rename(from, to); // throws if to exists
// after
if (host.exists(to)) {
  host.delete(to); // or rename to a backup first
}
host.rename(from, to);
Defensive patterns

Strategy: validation

Validate before calling

import { normalize, Path } from '@angular-devkit/core';

function renameSafe(host: { exists(p: Path): boolean; delete(p: Path): void; rename(f: Path, t: Path): void }, from: Path, to: Path): void {
  const dest = normalize(to);
  if (host.exists(dest)) {
    host.delete(dest); // or back it up first
  }
  host.rename(normalize(from), dest);
}

Try / catch

import { FileAlreadyExistException } from '@angular-devkit/core';

try {
  host.rename(from, to);
} catch (e) {
  if (e instanceof FileAlreadyExistException) {
    host.delete(e.path);
    host.rename(from, to);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling host.rename(from, to) where a file or directory already occupies `to` (e.g. from a previous write or rename); rerunning an idempotent operation without cleanup so the destination was created in an earlier run of the same host.

Common situations: Upgrade/migration schematics renaming 'a.ts' to 'b.ts' where 'b.ts' already exists; collision when two generated files map to the same target name; repeated execution of a one-shot rename within a long-lived builder process.

Related errors


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