{"record":{"id":"675a69a187308cac","repo":"JetBrains/intellij-community","slug":"starting-index-startingidx-is-greater-tha","errorCode":null,"errorMessage":"\"Starting index \" + startingIdx + \" is greater than the total number of rows \" + getRowsNum() + \". Starting index should be less or equal to \" + getRowsNum()","messagePattern":"\"Starting index \" \\+ startingIdx \\+ \" is greater than the total number of rows \" \\+ getRowsNum\\(\\) \\+ \"\\. Starting index should be less or equal to \" \\+ getRowsNum\\(\\)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"grid/core-impl/src/datagrid/DynamicNestedTable.java","lineNumber":171,"sourceCode":"  @Override\n  public void addRow(@NotNull GridRow value) {\n    myRows.add(new Row(value.getRowNum(), GridRow.getValues(value)));\n  }\n\n  @Override\n  public void removeRow(int rowIdx) {\n    myRows.remove(rowIdx);\n  }\n\n  @Override\n  public int getRowNum(int modelRowIdx) {\n    return myRows.get(modelRowIdx).rowNum;\n  }\n\n  @Override\n  public void insertRows(int startingIdx, List<GridRow> rows) {\n    if (startingIdx > getRowsNum()) {\n      throw new IllegalArgumentException(\n        \"Starting index \" +\n        startingIdx +\n        \" is greater than the total number of rows \" +\n        getRowsNum() +\n        \". Starting index should be less or equal to \" +\n        getRowsNum()\n      );\n    }\n\n    // Correctly replace existing rows with new rows from the list\n    int endIndex = min(startingIdx + rows.size(), getRowsNum());\n    for (int i = startingIdx; i < endIndex; ++i) {\n      setRow(i, rows.get(i - startingIdx)); // Use (i - startingIdx) to correctly index into 'rows'\n    }\n\n    // Add any remaining new rows beyond the existing table size\n    if (rows.size() > getRowsNum() - startingIdx) {\n      for (int i = endIndex; i < startingIdx + rows.size(); ++i) {","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/JetBrains/intellij-community/blob/be881553f2a76ac8b4ea53950d93f0de78295c19/grid/core-impl/src/datagrid/DynamicNestedTable.java#L153-L189","documentation":"DynamicNestedTable.insertRows(int, List<GridRow>) throws IllegalArgumentException when startingIdx exceeds the current row count. Insertion at the very end (startingIdx == getRowsNum()) is legal; anything beyond that would leave a gap in the row list.","triggerScenarios":"Calling insertRows after rows were concurrently removed so that a previously valid startingIdx now exceeds the count; computing the insert position as rowsNum() + offset; passing an already-shifted index after an earlier insert in the same batch.","commonSituations":"Paste/drag-drop of multiple row blocks where each block's index is precomputed; a table refresh shrinking the row list between index calculation and the insert call.","solutions":["Clamp: use Math.min(startingIdx, table.getRowsNum()) when appending at the end is the intended semantics.","Recompute startingIdx from the live row count immediately before each insertRows call.","Insert blocks in descending original-index order so earlier inserts do not shift later positions."],"exampleFix":"// before\ntable.insertRows(startingIdx, rows);\n\n// after\nint safeIdx = Math.min(startingIdx, table.getRowsNum());\ntable.insertRows(safeIdx, rows);","handlingStrategy":"validation","validationCode":"int safeIdx = Math.min(startingIdx, table.getRowsNum());\ntable.insertRows(safeIdx, rows);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp insertion indexes to the live row count.","When inserting multiple blocks, recompute each block's index after the previous insert."],"tags":["datagrid","nested-table","row-mutation","paste"],"backgroundTag":null,"analyzedSha":"be881553f2a76ac8b4ea53950d93f0de78295c19","analyzedAt":"2026-08-14T14:13:06.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}