PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

First sheet index must be a positive integer.

Error message

First sheet index must be a positive integer.

What it means

Spreadsheet::setFirstSheetIndex(int) sets which tab the workbook view scrolls to first (the first visible tab in the sheet tab bar when the file opens). Any value below zero throws 'First sheet index must be a positive integer.' — although the message says 'positive', the code actually accepts 0 (the first sheet); only negatives are rejected.

Source

Thrown at src/PhpSpreadsheet/Spreadsheet.php:1639

     *
     * @return int First sheet in book view
     */
    public function getFirstSheetIndex(): int
    {
        return $this->firstSheetIndex;
    }

    /**
     * Set the first sheet in the book view.
     *
     * @param int $firstSheetIndex First sheet in book view
     */
    public function setFirstSheetIndex(int $firstSheetIndex): void
    {
        if ($firstSheetIndex >= 0) {
            $this->firstSheetIndex = (int) $firstSheetIndex;
        } else {
            throw new Exception('First sheet index must be a positive integer.');
        }
    }

    /**
     * Return the visibility status of the workbook.
     *
     * This may be one of the following three values:
     * - visibile
     *
     * @return string Visible status
     */
    public function getVisibility(): string
    {
        return $this->visibility;
    }

    /**
     * Set the visibility status of the workbook.

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Clamp to a valid range: $first = max(0, min($first, $spreadsheet->getSheetCount() - 1)); before calling.
  2. Map 'no preference' sentinels (-1, null) to 0 explicitly instead of passing them through.
  3. Use setActiveSheetIndexByName()/by valid index when the intent is 'open on a specific tab'.

Example fix

// before
$spreadsheet->setFirstSheetIndex($selected - 1); // throws when $selected === 0

// after
$spreadsheet->setFirstSheetIndex(max(0, $selected - 1));
Defensive patterns

Strategy: validation

Validate before calling

$max = $spreadsheet->getSheetCount() - 1;
$spreadsheet->setFirstSheetIndex(max(0, min($firstSheetIndex, $max)));

Type guard

function isValidFirstSheetIndex(\PhpOffice\PhpSpreadsheet\Spreadsheet $s, int $i): bool
{
    return $i >= 0;
}

Try / catch

try {
    $spreadsheet->setFirstSheetIndex($index);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    $spreadsheet->setFirstSheetIndex(0);
}

Prevention

When it happens

Trigger: setFirstSheetIndex(-1) from an off-by-one computation (e.g. $index - 1 when $index is 0); passing a 'not selected' sentinel like -1 from UI code; arithmetic on an index variable that can legitimately reach -1.

Common situations: Form/CLI input where 'no preference' is encoded as -1 and forwarded verbatim; computations like setFirstSheetIndex($activeIndex - 1) used to show the tab before the active one; casting null or failed intval() input (0 is fine, but -1 sentinels are not).

Related errors


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