angular/angular-cli · error · IndexOutOfBoundException

Index ${index} outside of range [0, ${this.content.original.

Error message

Index ${index} outside of range [0, ${this.content.original.length}].

What it means

UpdateRecorderBase._assertIndex validates that every edit position falls within [0, fileLength] before recording an insert or removal; otherwise it throws IndexOutOfBoundException. It fires when insertLeft, insertRight, or remove are called with an index beyond the file's original content length.

Source

Thrown at packages/angular_devkit/schematics/src/tree/recorder.ts:68

    // Check if we're BOM.
    if (c0 == 0xef && c1 == 0xbb && c2 == 0xbf) {
      return new UpdateRecorderBase(entry.content, entry.path, 'utf-8', true);
    } else if (c0 === 0xff && c1 == 0xfe) {
      return new UpdateRecorderBase(entry.content, entry.path, 'utf-16le', true);
    } else if (c0 === 0xfe && c1 == 0xff) {
      return new UpdateRecorderBase(entry.content, entry.path, 'utf-16be', true);
    }

    return new UpdateRecorderBase(entry.content, entry.path);
  }

  get path(): string {
    return this._path;
  }

  protected _assertIndex(index: number): void {
    if (index < 0 || index > this.content.original.length) {
      throw new IndexOutOfBoundException(index, 0, this.content.original.length);
    }
  }

  // These just record changes.
  insertLeft(index: number, content: Buffer | string): UpdateRecorder {
    this._assertIndex(index);
    this.content.appendLeft(index, content.toString());

    return this;
  }

  insertRight(index: number, content: Buffer | string): UpdateRecorder {
    this._assertIndex(index);
    this.content.appendRight(index, content.toString());

    return this;
  }

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Clamp or validate the index: only call insert/remove when 0 <= index <= (tree.read(path)?.length ?? 0).
  2. Recompute offsets from the current file content right before editing instead of caching them.
  3. Handle search misses (indexOf === -1) by throwing a descriptive error instead of using the index.

Example fix

// before
const idx = content.indexOf(marker); // -1 on miss
recorder.insertLeft(idx, snippet);
// after
const idx = content.indexOf(marker);
if (idx === -1 || idx > content.length) {
  throw new SchematicsException(`Marker not found in ${path}`);
}
recorder.insertLeft(idx, snippet);
Defensive patterns

Strategy: validation

Validate before calling

function canEditAt(buf: Buffer | null, index: number): boolean {
  return buf !== null && Number.isInteger(index) && index >= 0 && index <= buf.length;
}

Type guard

function isValidIndex(index: number, content: Buffer | string): boolean {
  return Number.isInteger(index) && index >= 0 && index <= content.length;
}

Try / catch

try {
  recorder.insertLeft(index, snippet);
} catch (e) {
  if (e instanceof IndexOutOfBoundException) {
    throw new SchematicsException(`Edit offset ${index} out of range [0, ${e.length}]`);
  }
  throw e;
}

Prevention

When it happens

Trigger: recorder.insertLeft(index, ...) / insertRight / remove with index < 0 or index > content.original.length — typically when a computed offset comes from stale search results, an empty file, or a different file's content.

Common situations: Regex/string search returning -1 then used as an offset; editing files that got truncated or emptied; off-by-one on length; reusing offsets computed against an older file version (version-change drift).

Related errors


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