{"record":{"id":"7f7e00dfb757ceef","repo":"PHPOffice/PhpSpreadsheet","slug":"cellrange-array-length-must-be-2-or-4","errorCode":null,"errorMessage":"CellRange array length must be 2 or 4","messagePattern":"CellRange array length must be 2 or 4","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Worksheet/Validations.php","lineNumber":105,"sourceCode":"            $addressRange = self::convertWholeRowColumn($addressRange);\n\n            return empty($worksheet) ? strtoupper($addressRange) : $worksheet . '!' . strtoupper($addressRange);\n        }\n\n        if (is_array($cellRange)) {\n            switch (count($cellRange)) {\n                case 4:\n                    $from = [$cellRange[0], $cellRange[1]];\n                    $to = [$cellRange[2], $cellRange[3]];\n\n                    break;\n                case 2:\n                    $from = [$cellRange[0], $cellRange[1]];\n                    $to = [$cellRange[0], $cellRange[1]];\n\n                    break;\n                default:\n                    throw new SpreadsheetException('CellRange array length must be 2 or 4');\n            }\n            $cellRange = new CellRange(CellAddress::fromColumnRowArray($from), CellAddress::fromColumnRowArray($to));\n        }\n\n        return (string) $cellRange;\n    }\n\n    public static function definedNameToCoordinate(string $coordinate, Worksheet $worksheet): string\n    {\n        // Uppercase coordinate\n        $coordinate = strtoupper($coordinate);\n        // Eliminate leading equal sign\n        $testCoordinate = Preg::replace('/^=/', '', $coordinate);\n        $defined = $worksheet->getParentOrThrow()->getDefinedName($testCoordinate, $worksheet);\n        if ($defined !== null) {\n            if ($defined->getWorksheet() === $worksheet && !$defined->isFormula()) {\n                $coordinate = Preg::replace('/^=/', '', $defined->getValue());\n            }","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Worksheet/Validations.php#L87-L123","documentation":"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.","triggerScenarios":"$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.","commonSituations":"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.","solutions":["Use the 2-element [columnIndex, row] or 4-element [fromCol, fromRow, toCol, toRow] integer array form","Or skip arrays entirely: pass a string 'A1:B2' or a CellRange/AddressRange object","count($range) === 2 || count($range) === 4 before calling mergeCells()"],"exampleFix":"// before\n$sheet->mergeCells([3, 5, 6]); // count 3 -> throws\n\n// after\n$sheet->mergeCells([3, 5, 6, 8]); // C5:F8\n// or\n$sheet->mergeCells('C5:F8');","handlingStrategy":"type-guard","validationCode":"if (is_array($range) && !in_array(count($range), [2, 4], true)) {\n    throw new InvalidArgumentException('CellRange array must have exactly 2 or 4 elements');\n}\n$sheet->mergeCells($range);","typeGuard":"/** @param mixed $range */\nfunction isAcceptableRangeArgument($range): bool\n{\n    if (is_string($range) || $range instanceof \\PhpOffice\\PhpSpreadsheet\\Cell\\AddressRange) {\n        return true;\n    }\n\n    return is_array($range) && in_array(count($range), [2, 4], true);\n}","tryCatchPattern":null,"preventionTips":["Prefer the string 'A1:B2' or [fromCol, fromRow, toCol, toRow] forms consistently across the codebase","Never build the array by pushing optional bounds — assign all four positions explicitly","Document the 2-or-4 contract wherever you accept dynamic ranges"],"tags":["phpspreadsheet","validation","cell-range","array-shape","merge"],"backgroundTag":"invalid-array-shape","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}