PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

CellRange array length must be 2 or 4

Error message

CellRange array length must be 2 or 4

What it means

Thrown by Validations::validateCellRange() when the range is supplied as a PHP array whose count() is not 2 or 4. The accepted array forms are exactly [columnIndex, row] (single cell, values duplicated to from/to) and [fromColumnIndex, fromRow, toColumnIndex, toRow]; any other length cannot describe a rectangle.

Source

Thrown at src/PhpSpreadsheet/Worksheet/Validations.php:105

            $addressRange = self::convertWholeRowColumn($addressRange);

            return empty($worksheet) ? strtoupper($addressRange) : $worksheet . '!' . strtoupper($addressRange);
        }

        if (is_array($cellRange)) {
            switch (count($cellRange)) {
                case 4:
                    $from = [$cellRange[0], $cellRange[1]];
                    $to = [$cellRange[2], $cellRange[3]];

                    break;
                case 2:
                    $from = [$cellRange[0], $cellRange[1]];
                    $to = [$cellRange[0], $cellRange[1]];

                    break;
                default:
                    throw new SpreadsheetException('CellRange array length must be 2 or 4');
            }
            $cellRange = new CellRange(CellAddress::fromColumnRowArray($from), CellAddress::fromColumnRowArray($to));
        }

        return (string) $cellRange;
    }

    public static function definedNameToCoordinate(string $coordinate, Worksheet $worksheet): string
    {
        // Uppercase coordinate
        $coordinate = strtoupper($coordinate);
        // Eliminate leading equal sign
        $testCoordinate = Preg::replace('/^=/', '', $coordinate);
        $defined = $worksheet->getParentOrThrow()->getDefinedName($testCoordinate, $worksheet);
        if ($defined !== null) {
            if ($defined->getWorksheet() === $worksheet && !$defined->isFormula()) {
                $coordinate = Preg::replace('/^=/', '', $defined->getValue());
            }

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Use the 2-element [columnIndex, row] or 4-element [fromCol, fromRow, toCol, toRow] integer array form
  2. Or skip arrays entirely: pass a string 'A1:B2' or a CellRange/AddressRange object
  3. count($range) === 2 || count($range) === 4 before calling mergeCells()

Example fix

// before
$sheet->mergeCells([3, 5, 6]); // count 3 -> throws

// after
$sheet->mergeCells([3, 5, 6, 8]); // C5:F8
// or
$sheet->mergeCells('C5:F8');
Defensive patterns

Strategy: type-guard

Validate before calling

if (is_array($range) && !in_array(count($range), [2, 4], true)) {
    throw new InvalidArgumentException('CellRange array must have exactly 2 or 4 elements');
}
$sheet->mergeCells($range);

Type guard

/** @param mixed $range */
function isAcceptableRangeArgument($range): bool
{
    if (is_string($range) || $range instanceof \PhpOffice\PhpSpreadsheet\Cell\AddressRange) {
        return true;
    }

    return is_array($range) && in_array(count($range), [2, 4], true);
}

Prevention

When it happens

Trigger: $sheet->mergeCells([1, 2, 3]) (count 3); passing a nested pair like [[1,2],[3,4]]; passing [] or a flat list with 5+ entries to mergeCells(), unmergeCells() or any other API routed through validateCellRange.

Common situations: Building ranges from dynamic data where one bound is missing/null so count() ends up odd; copy-pasting a 3-element [from, to, extra] array from application code; assuming nested coordinate pairs are supported.

Related errors


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