PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

dggContainer is unexpectedly null

Error message

dggContainer is unexpectedly null

What it means

Shared\Escher models the binary Escher drawing structures of .xls files; getDggContainerOrThrow() returns the drawing-group container or throws when it was never set (src/PhpSpreadsheet/Shared/Escher.php:32). The Xls reader dereferences it when reading workbook-level images: getDggContainerOrThrow()->getBstoreContainerOrThrow() in src/PhpSpreadsheet/Reader/Xls/LoadSpreadsheet.php:500, so the throw means the Escher stream lacked the Dgg container.

Source

Thrown at src/PhpSpreadsheet/Shared/Escher.php:32

    /**
     * Drawing Container.
     */
    private ?Escher\DgContainer $dgContainer = null;

    /**
     * Get Drawing Group Container.
     */
    public function getDggContainer(): ?Escher\DggContainer
    {
        return $this->dggContainer;
    }

    /**
     * Get Drawing Group Container.
     */
    public function getDggContainerOrThrow(): Escher\DggContainer
    {
        return $this->dggContainer ?? throw new SpreadsheetException('dggContainer is unexpectedly null');
    }

    /**
     * Set Drawing Group Container.
     */
    public function setDggContainer(Escher\DggContainer $dggContainer): Escher\DggContainer
    {
        return $this->dggContainer = $dggContainer;
    }

    /**
     * Get Drawing Container.
     */
    public function getDgContainer(): ?Escher\DgContainer
    {
        return $this->dgContainer;
    }

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Re-save the workbook in Excel or LibreOffice (open + save) to rebuild a complete Escher structure, or convert to .xlsx
  2. Strip drawings before processing if images are irrelevant: convert to CSV/xlsx without images
  3. Catch the exception around load and quarantine/reject the specific file in batch pipelines
  4. Update PhpSpreadsheet — these OrThrow accessors replaced silent null handling, and reader robustness improves across releases
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check file integrity before the reader dereferences Escher containers
$zipCheck = true; // OLE2 files: verify size > 0 and signature
$fh = fopen($path, 'rb');
$sig = fread($fh, 8);
fclose($fh);
if ($sig !== "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1") {
    $zipCheck = false;
}
if (!$zipCheck) {
    throw new InvalidArgumentException('Not a valid .xls workbook');
}

Try / catch

try {
    $spreadsheet = $reader->load($path);
} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
    if (str_contains($e->getMessage(), 'dggContainer')) {
        // malformed Escher drawing group: route to repair/re-save pipeline
    }
}

Prevention

When it happens

Trigger: Reading an .xls with drawings where the workbook-level Escher record set is truncated or omits the drawing-group container — typically files emitted by legacy exporters (SAP, old reporting tools) or corrupted downloads — while sheet-level records still advertise images.

Common situations: Enterprise report archives processed in batch; files that survived partial transfers; workbooks from non-Excel writers with incomplete Escher implementations.

Related errors


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