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
- Clamp to a valid range: $first = max(0, min($first, $spreadsheet->getSheetCount() - 1)); before calling.
- Map 'no preference' sentinels (-1, null) to 0 explicitly instead of passing them through.
- 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
- Map 'none' sentinels (-1, null) to 0 before calling.
- Clamp computed indexes with max(0, ...).
- Remember the API is 0-based and accepts 0.
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
- Invalid visibility value.
- Tab ratio must be between 0 and 1000.
- Invalid R1C1-format Cell Reference
- Invalid A1-format Cell Reference
- File doesn't seem to be an OLE container.
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/99071324f4b97cde.
Report an issue: GitHub.