PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Your requested sheet index: {$sheetIndex} is out of bounds.
Error message
Your requested sheet index: {$sheetIndex} is out of bounds. The actual number of sheets is {$numSheets}. What it means
Spreadsheet::getSheet(int $index) returns the worksheet at a 0-based position and throws when no sheet is stored at that offset (isset() on the collection fails). The message echoes the requested index and the actual sheet count. It is the standard guard for positional access to the sheet collection.
Source
Thrown at src/PhpSpreadsheet/Spreadsheet.php:700
if (
($this->activeSheetIndex >= $sheetIndex)
&& ($this->activeSheetIndex > 0 || $numSheets <= 1)
) {
--$this->activeSheetIndex;
}
}
/**
* Get sheet by index.
*
* @param int $sheetIndex Sheet index
*/
public function getSheet(int $sheetIndex): Worksheet
{
if (!isset($this->workSheetCollection[$sheetIndex])) {
$numSheets = $this->getSheetCount();
throw new Exception(
"Your requested sheet index: {$sheetIndex} is out of bounds. The actual number of sheets is {$numSheets}."
);
}
return $this->workSheetCollection[$sheetIndex];
}
/**
* Get all sheets.
*
* @return Worksheet[]
*/
public function getAllSheets(): array
{
return $this->workSheetCollection;
}
/**View on GitHub (pinned to 65b080eef4)
Solutions
- Guard the call: if ($index >= 0 && $index < $spreadsheet->getSheetCount()) { $sheet = $spreadsheet->getSheet($index); }
- Iterate safely over all sheets: foreach ($spreadsheet->getSheets() as $sheet) { ... } instead of indexed loops.
- Fetch by name when possible: $spreadsheet->getSheetByNameOrThrow('Data').
- Re-count inside loops that add or remove sheets: use $spreadsheet->getSheetCount() at each iteration.
Example fix
// before
$sheet = $spreadsheet->getSheet(2); // throws: index out of bounds
// after
$sheet = $spreadsheet->getSheetCount() > 2
? $spreadsheet->getSheet(2)
: $spreadsheet->getSheetByNameOrThrow('Data'); Defensive patterns
Strategy: validation
Validate before calling
if ($index >= 0 && $index < $spreadsheet->getSheetCount()) {
$sheet = $spreadsheet->getSheet($index);
} Type guard
function sheetIndexExists(\PhpOffice\PhpSpreadsheet\Spreadsheet $s, int $i): bool
{
return $i >= 0 && $i < $s->getSheetCount();
} Try / catch
try {
$sheet = $spreadsheet->getSheet($index);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
$sheet = $spreadsheet->getSheetByNameOrThrow($spreadsheet->getSheetNames()[0]);
} Prevention
- Iterate with foreach ($spreadsheet->getSheets() as $sheet) instead of indexed for loops.
- Validate file shape (expected tabs) right after loading.
- Prefer name-based access when the target is known by title.
When it happens
Trigger: getSheet(1) on a workbook with a single sheet; getSheet($i) inside a for loop bounded by a stale count taken before sheets were removed; getSheet($n) where $n comes from user input or a config default that assumes a template layout which the loaded file does not have.
Common situations: Reports that assume a fixed template ('data goes on sheet 2') opened against a user-supplied file with fewer tabs; iterating sheets with a cached count; code written against a fixture workbook then run on trimmed-down production files.
Related errors
- You tried to remove a sheet by the out of bounds index: {$sh
- You tried to set a sheet active by the out of bounds index:
- Token with id $id does not exist.
- Cannot update when cell is not bound to a worksheet
- Cannot get column when cell is not bound to a worksheet
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/594b03c906fbe276.
Report an issue: GitHub.