PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

Only cell ranges may be passed to this method.

Error message

Only cell ranges may be passed to this method.

What it means

updateCellRange() is a private ReferenceHelper helper (the engine behind insertNewBefore/insertRows/removeColumn) that only accepts strings Coordinate::coordinateIsRange() classifies as a range, i.e. containing a ':' separator. Its only caller (updateCellReference at src/PhpSpreadsheet/ReferenceHelper.php:1048) branches single-cell references away first, so hitting this throw means reference metadata inside the workbook degraded to a non-range form mid-processing. It is effectively an internal invariant guard, not a public API validation.

Source

Thrown at src/PhpSpreadsheet/ReferenceHelper.php:1137

             *      them with a #REF!
             */
            $formula = $definedName->getValue();
            $formula = $this->updateFormulaReferences($formula, $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle(), true);
            $definedName->setValue($formula);
        }
    }

    /**
     * Update cell range.
     *
     * @param string $cellRange Cell range    (e.g. 'B2:D4', 'B:C' or '2:3')
     *
     * @return string Updated cell range
     */
    private function updateCellRange(string $cellRange = 'A1:A1', bool $includeAbsoluteReferences = false, bool $onlyAbsoluteReferences = false): string
    {
        if (!Coordinate::coordinateIsRange($cellRange)) {
            throw new Exception('Only cell ranges may be passed to this method.');
        }

        // Update range
        $range = Coordinate::splitRange($cellRange);
        $ic = count($range);
        for ($i = 0; $i < $ic; ++$i) {
            $jc = count($range[$i]);
            for ($j = 0; $j < $jc; ++$j) {
                /** @var CellReferenceHelper */
                $cellReferenceHelper = $this->cellReferenceHelper;
                if (ctype_alpha($range[$i][$j])) {
                    $range[$i][$j] = Coordinate::coordinateFromString(
                        $cellReferenceHelper->updateCellReference($range[$i][$j] . '1', $includeAbsoluteReferences, $onlyAbsoluteReferences, null)
                    )[0];
                } elseif (ctype_digit($range[$i][$j])) {
                    $range[$i][$j] = Coordinate::coordinateFromString(
                        $cellReferenceHelper->updateCellReference('A' . $range[$i][$j], $includeAbsoluteReferences, $onlyAbsoluteReferences, null)
                    )[1];

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Update to the latest PhpSpreadsheet patch release; several insert/delete reference-adjustment bugs have been fixed over time
  2. Inspect $spreadsheet->getDefinedNames() and getPrintArea() for each sheet; remove or rewrite malformed/single-cell entries before inserting rows
  3. Reproduce with a minimal workbook and report upstream, since this guard should be unreachable through the public API
  4. Do not call ReferenceHelper internals via reflection
Defensive patterns

Strategy: validation

Validate before calling

// Before insert/delete, audit range-like metadata for non-range values
foreach ($spreadsheet->getDefinedNames() as $name => $def) {
    $value = $def->getValue();
    if ($value !== null && !str_contains($value, ':') && preg_match('/^[A-Z]+[0-9]+$/i', $value)) {
        // single-cell stored where range expected: normalize or drop
        $spreadsheet->removeNamedRange($name);
    }
}

Type guard

function isCellRangeString(string $ref): bool
{
    return \PhpOffice\PhpSpreadsheet\Cell\Coordinate::coordinateIsRange($ref);
}

Try / catch

try {
    $sheet->insertNewBefore('A1', 0, 1);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    if (str_contains($e->getMessage(), 'Only cell ranges')) {
        // corrupt reference metadata: report the workbook, skip structural edits
    }
}

Prevention

When it happens

Trigger: Running $sheet->insertNewBefore(), insertRows(), removeColumn(), or updateNamedRanges() on a workbook whose defined names, print areas, or data-validation ranges hold malformed values (e.g. a stored range that collapses to a single cell after earlier mutations); invoking the private method through reflection or a forked copy of the class.

Common situations: Workbooks loaded from untrusted/corrupt sources; repeated insert/delete cycles that shrink a named range to one cell and leave stale metadata; bugs in older PhpSpreadsheet releases around named-range adjustment.


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