PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

Scale must not be negative

Error message

Scale must not be negative

What it means

PageSetup::setScale() stores the print zoom percentage for a worksheet. Excel's UI only permits 10-400, but the file format tolerates any non-negative integer (0 is written and Excel reads it as 100) and null resets to 100; the only rejected input is a negative integer, which throws 'Scale must not be negative'. Note that a successful setScale($scale, true) also disables fitToPage.

Source

Thrown at src/PhpSpreadsheet/Worksheet/PageSetup.php:353

     * Set Scale.
     * Print scaling. Valid values range from 10 to 400
     * This setting is overridden when fitToWidth and/or fitToHeight are in use.
     *
     * @param bool $update Update fitToPage so scaling applies rather than fitToHeight / fitToWidth
     *
     * @return $this
     */
    public function setScale(?int $scale, bool $update = true): static
    {
        // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface,
        // but it is apparently still able to handle any scale >= 0, where 0 results in 100
        if ($scale === null || $scale >= 0) {
            $this->scale = $scale;
            if ($update) {
                $this->fitToPage = false;
            }
        } else {
            throw new PhpSpreadsheetException('Scale must not be negative');
        }

        return $this;
    }

    /**
     * Get Fit To Page.
     */
    public function getFitToPage(): bool
    {
        return $this->fitToPage;
    }

    /**
     * Set Fit To Page.
     *
     * @return $this
     */

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Clamp before setting: setScale(max(0, $scale)).
  2. If the goal is automatic sizing, use setFitToPage/setFitToWidth/setFitToHeight instead of computing a scale.
  3. Validate and cast numeric input before it reaches page setup.

Example fix

// before
$sheet->getPageSetup()->setScale($zoom); // $zoom = -20 -> throws

// after
$sheet->getPageSetup()->setScale(max(0, (int) $zoom));
Defensive patterns

Strategy: validation

Validate before calling

$scale = max(0, (int) $zoom);
$sheet->getPageSetup()->setScale($scale);

Type guard

function isValidPrintScale(?int $scale): bool
{
    return $scale === null || $scale >= 0;
}

Try / catch

try {
    $sheet->getPageSetup()->setScale($scale);
} catch (PhpSpreadsheetException $e) {
    $sheet->getPageSetup()->setScale(100);
}

Prevention

When it happens

Trigger: $sheet->getPageSetup()->setScale(-15); a computed percentage going negative (e.g. 100 - $reduction * 100 style math); unvalidated user input like '-50' cast to int.

Common situations: Zoom derived arithmetically from data or request parameters; sanitized-too-late form input; porting code from libraries that clamped silently.

Related errors


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