PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Cloning a Singleton is not allowed!
Error message
Cloning a Singleton is not allowed!
What it means
ReferenceHelper is a singleton obtained via ReferenceHelper::getInstance(); its __clone is declared final and unconditionally throws, enforcing the singleton contract at the language level. The library does this so no second helper instance can drift out of sync with the one wired into the spreadsheet's insert/delete machinery.
Source
Thrown at src/PhpSpreadsheet/ReferenceHelper.php:1409
// Style
$coordinate = Coordinate::stringFromColumnIndex($i) . ($beforeRow - 1);
if ($worksheet->cellExists($coordinate)) {
$xfIndex = $worksheet->getCell($coordinate)->getXfIndex();
for ($j = $beforeRow; $j <= $beforeRow - 1 + $numberOfRows; ++$j) {
if (!empty($xfIndex) || $worksheet->cellExists([$i, $j])) {
$worksheet->getCell(Coordinate::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex);
}
}
}
}
}
/**
* __clone implementation. Cloning should not be allowed in a Singleton!
*/
final public function __clone()
{
throw new Exception('Cloning a Singleton is not allowed!');
}
}
View on GitHub (pinned to 65b080eef4)
Solutions
- Drop the clone and call ReferenceHelper::getInstance() wherever the helper is needed; it always returns the same shared instance
- If you need an independent copy of document state, copy the Spreadsheet (copy() / duplicate sheets), not the helper
- In generic deep-clone walkers, skip singletons or objects whose __clone throws
Example fix
// before $helper = ReferenceHelper::getInstance(); $copy = clone $helper; // throws: Cloning a Singleton is not allowed! // after $helper = ReferenceHelper::getInstance(); // reuse the shared instance
Defensive patterns
Strategy: validation
Validate before calling
// Refuse to clone known singletons before a generic deep-clone walk
function safeClone(mixed $obj): mixed
{
if ($obj instanceof \PhpOffice\PhpSpreadsheet\ReferenceHelper) {
return \PhpOffice\PhpSpreadsheet\ReferenceHelper::getInstance();
}
return clone $obj;
} Type guard
function isCloneableService(object $obj): bool
{
return !($obj instanceof \PhpOffice\PhpSpreadsheet\ReferenceHelper);
} Prevention
- Fetch singletons via getInstance() at each use site; never store a clone
- In deep-clone helpers, skip objects exposing __clone or documented singletons
- Snapshot document state via Spreadsheet copy, not helper cloning
When it happens
Trigger: Any direct clone of the singleton: $helper = ReferenceHelper::getInstance(); $copy = clone $helper; generic deep-clone utilities that blindly clone every object in a graph; prototype-style code applied to services it did not create.
Common situations: Copy/pasted 'deep clone' helpers that iterate object properties and clone everything; attempts to snapshot spreadsheet state by cloning internals; frameworks that clone services during container compilation.
Related errors
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/8749a4b461ac395a.
Report an issue: GitHub.