{"record":{"id":"72f26281c2b10bcd","repo":"krahets/hello-algo","slug":"index-out-of-bounds-exception-72f262","errorCode":null,"errorMessage":"Index Out Of Bounds Exception","messagePattern":"Index Out Of Bounds Exception","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"codes/typescript/chapter_graph/graph_adjacency_matrix.ts","lineNumber":52,"sourceCode":"        const n: number = this.size();\n        // 向顶点列表中添加新顶点的值\n        this.vertices.push(val);\n        // 在邻接矩阵中添加一行\n        const newRow: number[] = [];\n        for (let j: number = 0; j < n; j++) {\n            newRow.push(0);\n        }\n        this.adjMat.push(newRow);\n        // 在邻接矩阵中添加一列\n        for (const row of this.adjMat) {\n            row.push(0);\n        }\n    }\n\n    /* 删除顶点 */\n    removeVertex(index: number): void {\n        if (index >= this.size()) {\n            throw new RangeError('Index Out Of Bounds Exception');\n        }\n        // 在顶点列表中移除索引 index 的顶点\n        this.vertices.splice(index, 1);\n\n        // 在邻接矩阵中删除索引 index 的行\n        this.adjMat.splice(index, 1);\n        // 在邻接矩阵中删除索引 index 的列\n        for (const row of this.adjMat) {\n            row.splice(index, 1);\n        }\n    }\n\n    /* 添加边 */\n    // 参数 i, j 对应 vertices 元素索引\n    addEdge(i: number, j: number): void {\n        // 索引越界与相等处理\n        if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) {\n            throw new RangeError('Index Out Of Bounds Exception');","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/codes/typescript/chapter_graph/graph_adjacency_matrix.ts#L34-L70","documentation":"Thrown by GraphAdjMat.removeVertex() (a RangeError) when index >= this.size() (i.e. >= vertices.length). Note the guard is asymmetric: it checks the upper bound only and does NOT reject negative index, so a negative index will slip through to Array.splice and be interpreted as an offset-from-end — a latent bug rather than a thrown error for negatives. The intent is to block deletion of a non-existent vertex position.","triggerScenarios":"Calling removeVertex(index) with index >= number of vertices; calling on a graph that was shrunk below a stale index captured earlier. A negative index does not throw here but instead splices from the end — still a logic error, just silent.","commonSituations":"Using a stale vertex count after prior removeVertex calls shrank the array; off-by-one loop using <= size; confusing vertex value with vertex index (the matrix is indexed by position, not by the stored value).","solutions":["Validate both bounds yourself: if (index >= 0 && index < graph.size()) graph.removeVertex(index).","Treat the vertex index as a positional cursor that shifts after every removeVertex — recompute or iterate carefully when removing multiple vertices (remove highest index first).","If you mean to remove by value, find its index via graph.vertices.indexOf(val) and confirm >= 0.","Fix the class guard to also reject index < 0 if you control the source."],"exampleFix":"// before\ngraph.removeVertex(index); // throws if index >= size\n// after\nif (index >= 0 && index < graph.size()) graph.removeVertex(index);\n// when removing several, go high-to-low to keep indices stable\nindices.sort((a, b) => b - a).forEach(i => { if (i < graph.size()) graph.removeVertex(i); });","handlingStrategy":"validation","validationCode":"function safeRemoveVertex(graph, index) {\n  // guard BOTH bounds: the class only checks the upper bound\n  if (index >= 0 && index < graph.size()) { graph.removeVertex(index); return true; }\n  return false;\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["The class guard omits index < 0; validate the lower bound yourself.","When removing multiple vertices, process highest index first so lower indices stay valid.","Map vertex values to indices via indexOf and confirm >= 0.","Treat vertex index as positional — it shifts after every removeVertex."],"tags":["typescript","graph","index-out-of-bounds","validation","off-by-one"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}