PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
CellXf index is out of bounds.
Error message
CellXf index is out of bounds.
What it means
Spreadsheet::removeCellXfByIndex(int) deletes one entry from the shared cellXf style collection and then rewrites every cell whose xfIndex pointed above the removed slot (decrementing by one). The guard rejects an index greater than count-1 with 'CellXf index is out of bounds.' Removing styles by hand is low-level; most code should prune via garbageCollect().
Source
Thrown at src/PhpSpreadsheet/Spreadsheet.php:1336
/**
* Add a cellXf to the workbook.
*/
public function addCellXf(Style $style): void
{
$this->cellXfCollection[] = $style;
$style->setIndex(count($this->cellXfCollection) - 1);
}
/**
* Remove cellXf by index. It is ensured that all cells get their xf index updated.
*
* @param int $cellStyleIndex Index to cellXf
*/
public function removeCellXfByIndex(int $cellStyleIndex): void
{
if ($cellStyleIndex > count($this->cellXfCollection) - 1) {
throw new Exception('CellXf index is out of bounds.');
}
// first remove the cellXf
array_splice($this->cellXfCollection, $cellStyleIndex, 1);
// then update cellXf indexes for cells
foreach ($this->workSheetCollection as $worksheet) {
foreach ($worksheet->getCoordinates(false) as $coordinate) {
$cell = $worksheet->getCell($coordinate);
$xfIndex = $cell->getXfIndex();
if ($xfIndex > $cellStyleIndex) {
// decrease xf index by 1
$cell->setXfIndex($xfIndex - 1);
} elseif ($xfIndex == $cellStyleIndex) {
// set to default xf index 0
$cell->setXfIndex(0);
}
}View on GitHub (pinned to 65b080eef4)
Solutions
- Validate first: if ($i >= 0 && $i < count($spreadsheet->getCellXfCollection())) removeCellXfByIndex($i);
- Prefer $spreadsheet->garbageCollect(), which removes unreferenced cellXfs and fixes cell indexes atomically.
- When removing several, iterate from the highest index downward.
- Re-read count($spreadsheet->getCellXfCollection()) at each step instead of caching it.
Example fix
// before
$spreadsheet->removeCellXfByIndex(count($spreadsheet->getCellXfCollection())); // off-by-one
// after
$spreadsheet->garbageCollect(); // prune all unused styles safely
// or, for one slot:
$count = count($spreadsheet->getCellXfCollection());
if ($i >= 0 && $i < $count) {
$spreadsheet->removeCellXfByIndex($i);
} Defensive patterns
Strategy: validation
Validate before calling
if ($cellStyleIndex >= 0 && $cellStyleIndex < count($spreadsheet->getCellXfCollection())) {
$spreadsheet->removeCellXfByIndex($cellStyleIndex);
} Type guard
function isValidCellXfIndex(\PhpOffice\PhpSpreadsheet\Spreadsheet $s, int $i): bool
{
return $i >= 0 && $i < count($s->getCellXfCollection());
} Try / catch
try {
$spreadsheet->removeCellXfByIndex($i);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
// stale index — refresh and skip
error_log('cellXf removal skipped: ' . $e->getMessage());
} Prevention
- Prefer garbageCollect() over manual xf pruning.
- Remove from the highest index downward when pruning several.
- Re-read count(getCellXfCollection()) each iteration.
When it happens
Trigger: Calling removeCellXfByIndex($i) with $i >= count($spreadsheet->getCellXfCollection()); looping 'for ($i = 0; $i <= $count; $i++)' (off-by-one); using an xfIndex captured before earlier removals shrank the collection.
Common situations: Hand-rolled style-deduplication or memory-optimization code that prunes the xf collection; indexes taken from cell getXfIndex() but applied to a different workbook whose collection is smaller; iterating a snapshot of the collection while deleting from it.
Related errors
- No default style found for this workbook
- CellStyleXf index is out of bounds.
- Token with id $id does not exist.
- You tried to remove a sheet by the out of bounds index: {$sh
- Your requested sheet index: {$sheetIndex} is out of bounds.
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/43eb2428661ef36f.
Report an issue: GitHub.