PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

dgContainer is unexpectedly null

Error message

dgContainer is unexpectedly null

What it means

getDgContainerOrThrow() on Shared\Escher returns the per-sheet drawing container or throws when unset (src/PhpSpreadsheet/Shared/Escher.php:56). The Xls reader calls it unconditionally while reading worksheet drawings — $escherWorksheet->getDgContainerOrThrow()->getSpgrContainerOrThrow() at src/PhpSpreadsheet/Reader/Xls/LoadSpreadsheet.php:440 — so an Escher stream for a sheet without a valid Dg container triggers it.

Source

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

    public function setDggContainer(Escher\DggContainer $dggContainer): Escher\DggContainer
    {
        return $this->dggContainer = $dggContainer;
    }

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

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

    /**
     * Set Drawing Container.
     */
    public function setDgContainer(Escher\DgContainer $dgContainer): Escher\DgContainer
    {
        return $this->dgContainer = $dgContainer;
    }
}

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Re-save via Excel/LibreOffice to normalize drawing structures, or convert to .xlsx
  2. If drawings are not needed, convert to CSV or strip images before processing
  3. Catch and quarantine the file in automated pipelines; report the file as malformed
  4. Update PhpSpreadsheet to pick up reader robustness fixes
Defensive patterns

Strategy: try-catch

Validate before calling

// Cheap gate: skip the Xls reader entirely for non-OLE2 uploads (see error 187 helper)
if (!looksLikeOle2Spreadsheet($path)) {
    return reject('Corrupt .xls');
}

Try / catch

try {
    $spreadsheet = $reader->load($path);
} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
    if (str_contains($e->getMessage(), 'dgContainer')) {
        repairPipeline($path); // Excel/LibreOffice re-save, then retry once
    }
}

Prevention

When it happens

Trigger: Reading an .xls whose sheet-level Escher data is malformed or missing the Dg container while the surrounding records still indicate drawings exist (LoadSpreadsheet.php:440 dereferences both OrThrow accessors in one chain).

Common situations: Legacy third-party .xls generators with incomplete Escher output; corrupted drawing records after bad transfers; files edited by multiple old tools.

Related errors


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