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
- Update to the latest PhpSpreadsheet patch release; several insert/delete reference-adjustment bugs have been fixed over time
- Inspect $spreadsheet->getDefinedNames() and getPrintArea() for each sheet; remove or rewrite malformed/single-cell entries before inserting rows
- Reproduce with a minimal workbook and report upstream, since this guard should be unreachable through the public API
- 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
- Prefer insertRows()/removeRows() wrappers over raw insertNewBefore on suspect workbooks
- Sanitize defined names and print areas after loading untrusted files
- Keep PhpSpreadsheet current to get insert/delete adjustment fixes
- Never reach into ReferenceHelper privates via reflection
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.