{"record":{"id":"388a9b5bef437da0","repo":"angular/angular-cli","slug":"index-index-outside-of-range-0-this-content","errorCode":null,"errorMessage":"Index ${index} outside of range [0, ${this.content.original.length}].","messagePattern":"Index (.+?) outside of range \\[0, (.+?)\\]\\.","errorType":"exception","errorClass":"IndexOutOfBoundException","httpStatus":null,"severity":"error","filePath":"packages/angular_devkit/schematics/src/tree/recorder.ts","lineNumber":68,"sourceCode":"    // Check if we're BOM.\n    if (c0 == 0xef && c1 == 0xbb && c2 == 0xbf) {\n      return new UpdateRecorderBase(entry.content, entry.path, 'utf-8', true);\n    } else if (c0 === 0xff && c1 == 0xfe) {\n      return new UpdateRecorderBase(entry.content, entry.path, 'utf-16le', true);\n    } else if (c0 === 0xfe && c1 == 0xff) {\n      return new UpdateRecorderBase(entry.content, entry.path, 'utf-16be', true);\n    }\n\n    return new UpdateRecorderBase(entry.content, entry.path);\n  }\n\n  get path(): string {\n    return this._path;\n  }\n\n  protected _assertIndex(index: number): void {\n    if (index < 0 || index > this.content.original.length) {\n      throw new IndexOutOfBoundException(index, 0, this.content.original.length);\n    }\n  }\n\n  // These just record changes.\n  insertLeft(index: number, content: Buffer | string): UpdateRecorder {\n    this._assertIndex(index);\n    this.content.appendLeft(index, content.toString());\n\n    return this;\n  }\n\n  insertRight(index: number, content: Buffer | string): UpdateRecorder {\n    this._assertIndex(index);\n    this.content.appendRight(index, content.toString());\n\n    return this;\n  }\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/schematics/src/tree/recorder.ts#L50-L86","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Clamp or validate the index: only call insert/remove when 0 <= index <= (tree.read(path)?.length ?? 0).","Recompute offsets from the current file content right before editing instead of caching them.","Handle search misses (indexOf === -1) by throwing a descriptive error instead of using the index."],"exampleFix":"// before\nconst idx = content.indexOf(marker); // -1 on miss\nrecorder.insertLeft(idx, snippet);\n// after\nconst idx = content.indexOf(marker);\nif (idx === -1 || idx > content.length) {\n  throw new SchematicsException(`Marker not found in ${path}`);\n}\nrecorder.insertLeft(idx, snippet);","handlingStrategy":"validation","validationCode":"function canEditAt(buf: Buffer | null, index: number): boolean {\n  return buf !== null && Number.isInteger(index) && index >= 0 && index <= buf.length;\n}","typeGuard":"function isValidIndex(index: number, content: Buffer | string): boolean {\n  return Number.isInteger(index) && index >= 0 && index <= content.length;\n}","tryCatchPattern":"try {\n  recorder.insertLeft(index, snippet);\n} catch (e) {\n  if (e instanceof IndexOutOfBoundException) {\n    throw new SchematicsException(`Edit offset ${index} out of range [0, ${e.length}]`);\n  }\n  throw e;\n}","preventionTips":["Recompute offsets from fresh content immediately before each edit","Handle indexOf === -1 search misses explicitly","Clamp index with Math.min(index, content.length) when appending at end","Guard against negative offsets from substring arithmetic"],"tags":["index-out-of-bounds","schematics","recorder","offsets"],"backgroundTag":"index-out-of-bounds","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}