PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

spgrContainer is unexpectedly null

Error message

spgrContainer is unexpectedly null

What it means

DgContainer::getSpgrContainerOrThrow() returns the shape-group container of a sheet's drawing or throws when unset (src/PhpSpreadsheet/Shared/Escher/DgContainer.php:53). It is hit on read at src/PhpSpreadsheet/Reader/Xls/LoadSpreadsheet.php:440 (chained after getDgContainerOrThrow) and on write at src/PhpSpreadsheet/Writer/Xls/Escher.php:283, where the Xls writer counts shapes when saving drawings.

Source

Thrown at src/PhpSpreadsheet/Shared/Escher/DgContainer.php:53

    }

    public function setLastSpId(int $value): void
    {
        $this->lastSpId = $value;
    }

    public function getSpgrContainer(): ?SpgrContainer
    {
        return $this->spgrContainer;
    }

    public function getSpgrContainerOrThrow(): SpgrContainer
    {
        if ($this->spgrContainer !== null) {
            return $this->spgrContainer;
        }

        throw new SpreadsheetException('spgrContainer is unexpectedly null');
    }

    public function setSpgrContainer(SpgrContainer $spgrContainer): SpgrContainer
    {
        return $this->spgrContainer = $spgrContainer;
    }
}

View on GitHub (pinned to 65b080eef4)

Solutions

  1. On the read path: re-save the workbook in Excel/LibreOffice or convert to .xlsx to rebuild Escher data
  2. On the write path: attach complete Drawing objects via $sheet->getDrawingCollection() rather than building Escher containers manually
  3. Catch around load/save and quarantine the offending file; report it as malformed
  4. Update PhpSpreadsheet for reader/writer robustness fixes
Defensive patterns

Strategy: try-catch

Validate before calling

// Write path: ensure drawings go through the public API so containers are complete
$drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
$drawing->setPath($imagePath)->setCoordinates('B2');
$sheet->addDrawing($drawing); // builds a valid Spgr structure on save

Try / catch

try {
    $writer->save($outFile);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    if (str_contains($e->getMessage(), 'spgrContainer')) {
        // strip drawings, then save a drawing-free copy
        foreach ($sheet->getDrawingCollection() as $d) { /* remove */ }
    }
}

Prevention

When it happens

Trigger: Reading an .xls whose Dg container exists but contains no Spgr container (truncated Escher); writing an .xlsx→.xls conversion where the drawing object graph was built without a shape-group container (programmatic drawings assembled incompletely before save).

Common situations: Batch conversions hitting malformed legacy files; code that constructs Drawing objects or manipulates Escher structures directly and saves as .xls; corrupted archives.

Related errors


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