{"record":{"id":"05a30356b4c57905","repo":"PHPOffice/PhpSpreadsheet","slug":"rows-can-only-be-inserted-before-at-least-row-1","errorCode":null,"errorMessage":"Rows can only be inserted before at least row 1.","messagePattern":"Rows can only be inserted before at least row 1\\.","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Worksheet/Worksheet.php","lineNumber":2542,"sourceCode":"\n        return $this;\n    }\n\n    /**\n     * Insert a new row, updating all possible related data.\n     *\n     * @param int $before Insert before this row number\n     * @param int $numberOfRows Number of new rows to insert\n     *\n     * @return $this\n     */\n    public function insertNewRowBefore(int $before, int $numberOfRows = 1): static\n    {\n        if ($before >= 1) {\n            $objReferenceHelper = ReferenceHelper::getInstance();\n            $objReferenceHelper->insertNewBefore('A' . $before, 0, $numberOfRows, $this);\n        } else {\n            throw new Exception('Rows can only be inserted before at least row 1.');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Insert a new column, updating all possible related data.\n     *\n     * @param string $before Insert before this column Name, eg: 'A'\n     * @param int $numberOfColumns Number of new columns to insert\n     *\n     * @return $this\n     */\n    public function insertNewColumnBefore(string $before, int $numberOfColumns = 1): static\n    {\n        if (!is_numeric($before)) {\n            $objReferenceHelper = ReferenceHelper::getInstance();\n            $objReferenceHelper->insertNewBefore($before . '1', $numberOfColumns, 0, $this);","sourceCodeStart":2524,"sourceCodeEnd":2560,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Worksheet/Worksheet.php#L2524-L2560","documentation":"insertNewRowBefore(int $before, int $numberOfRows = 1) shifts existing rows down and inserts blanks before row $before via ReferenceHelper. Spreadsheet rows are 1-indexed, so the method requires $before >= 1 and throws immediately for 0 or negative values before any shifting work starts.","triggerScenarios":"insertNewRowBefore(0) or insertNewRowBefore(-3); a 0-based array index (foreach ($rows as $i => ...) with $i starting at 0) passed as the row number; offset arithmetic such as insertNewRowBefore($rowNumber - 1) evaluating to 0 when $rowNumber is 1.","commonSituations":"Classic zero-based vs one-base confusion when mapping PHP array positions to spreadsheet rows; importers computing an insertion point from CSV line numbers or database row offsets; refactors where a loop counter starting at 0 leaks into worksheet API calls.","solutions":["Pass a row number >= 1; to insert above the first row use insertNewRowBefore(1).","Convert 0-based positions at the boundary: insertNewRowBefore($zeroBasedIndex + 1, $count).","Clamp computed values: $before = max(1, $computed);","Audit loops that build row numbers from array keys; array_values($data) plus +1 removes the trap."],"exampleFix":"// before\nforeach ($data as $offset => $row) {\n    $sheet->insertNewRowBefore($offset, 1); // $offset starts at 0 -> throws\n}\n\n// after\nforeach (array_values($data) as $offset => $row) {\n    $sheet->insertNewRowBefore($offset + 1, 1);\n}","handlingStrategy":"validation","validationCode":"$insertAt = count($templateRows) + 1; // spreadsheet rows are 1-based\n$sheet->insertNewRowBefore(max(1, $insertAt), 2);","typeGuard":"/** Spreadsheet rows are 1-based: row 1 is the first row. */\nfunction isPositiveRow(int $row): bool\n{\n    return $row >= 1;\n}","tryCatchPattern":null,"preventionTips":["Treat every worksheet row/column argument as 1-based.","Convert array keys with + 1 exactly where data becomes spreadsheet coordinates.","Clamp computed insertion points with max(1, $n) instead of trusting upstream math."],"tags":["phpspreadsheet","worksheet","insert-row","row-index","argument-validation"],"backgroundTag":"off-by-one-index","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}