PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

You tried to set a sheet active by the out of bounds index:

Error message

You tried to set a sheet active by the out of bounds index: {$worksheetIndex}. The actual number of sheets is {$numSheets}.

What it means

Spreadsheet::setActiveSheetIndex(int) records which tab is selected when the file opens. It rejects an index beyond the last sheet with this message (the check is an upper-bound test: index > count-1 throws). The returned worksheet is the newly activated one.

Source

Thrown at src/PhpSpreadsheet/Spreadsheet.php:821

     *
     * @return int Active sheet index
     */
    public function getActiveSheetIndex(): int
    {
        return $this->activeSheetIndex;
    }

    /**
     * Set active sheet index.
     *
     * @param int $worksheetIndex Active sheet index
     */
    public function setActiveSheetIndex(int $worksheetIndex): Worksheet
    {
        $numSheets = count($this->workSheetCollection);

        if ($worksheetIndex > $numSheets - 1) {
            throw new Exception(
                "You tried to set a sheet active by the out of bounds index: {$worksheetIndex}. The actual number of sheets is {$numSheets}."
            );
        }
        $this->activeSheetIndex = $worksheetIndex;

        return $this->getActiveSheet();
    }

    /**
     * Set active sheet index by name.
     *
     * @param string $worksheetName Sheet title
     */
    public function setActiveSheetIndexByName(string $worksheetName): Worksheet
    {
        if (($worksheet = $this->getSheetByName($worksheetName)) instanceof Worksheet) {
            $this->setActiveSheetIndex($this->getIndex($worksheet));

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Clamp before calling: $index = max(0, min($index, $spreadsheet->getSheetCount() - 1));
  2. Prefer selecting by name: $spreadsheet->setActiveSheetIndexByName('Results').
  3. Recompute the count at call time inside loops that add/remove sheets.
  4. Convert 1-based user input to 0-based before calling.

Example fix

// before
$spreadsheet->setActiveSheetIndex(5); // throws when only 3 sheets

// after
$spreadsheet->setActiveSheetIndexByName('Results');
// or
$index = min(5, $spreadsheet->getSheetCount() - 1);
$spreadsheet->setActiveSheetIndex($index);
Defensive patterns

Strategy: validation

Validate before calling

$max = $spreadsheet->getSheetCount() - 1;
$spreadsheet->setActiveSheetIndex(max(0, min($index, $max)));

Type guard

function isValidActiveSheetIndex(\PhpOffice\PhpSpreadsheet\Spreadsheet $s, int $i): bool
{
    return $i >= 0 && $i < $s->getSheetCount();
}

Try / catch

try {
    $spreadsheet->setActiveSheetIndex($index);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    $spreadsheet->setActiveSheetIndex(0); // safe default: first tab
}

Prevention

When it happens

Trigger: setActiveSheetIndex(1) on a single-sheet workbook; a hard-coded 'open on the last tab' using a count captured before sheets were removed; activating an index derived from user input that is 1-based or stale.

Common situations: Export pipelines that always 'select the results sheet' by position while the template's tab count varies; code run after removeSheetByIndex() shrinks the collection; UI sheet pickers passing a 1-based number straight through.

Related errors


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/8d3328ca28835372. Report an issue: GitHub.