PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

bstoreContainer is unexpectedly null

Error message

bstoreContainer is unexpectedly null

What it means

DggContainer::getBstoreContainerOrThrow() returns the BLIP store (embedded image storage) of the workbook-level Escher or throws when unset (src/PhpSpreadsheet/Shared/Escher/DggContainer.php:104). The Xls reader chains it — getDggContainerOrThrow()->getBstoreContainerOrThrow() — at src/PhpSpreadsheet/Reader/Xls/LoadSpreadsheet.php:500 when resolving images referenced by sheet drawings.

Source

Thrown at src/PhpSpreadsheet/Shared/Escher/DggContainer.php:104

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

    /**
     * Get BLIP Store Container.
     */
    public function getBstoreContainer(): ?DggContainer\BstoreContainer
    {
        return $this->bstoreContainer;
    }

    /**
     * Get BLIP Store Container.
     */
    public function getBstoreContainerOrThrow(): DggContainer\BstoreContainer
    {
        return $this->bstoreContainer ?? throw new SpreadsheetException('bstoreContainer is unexpectedly null');
    }

    /**
     * Set BLIP Store Container.
     */
    public function setBstoreContainer(DggContainer\BstoreContainer $bstoreContainer): void
    {
        $this->bstoreContainer = $bstoreContainer;
    }

    /**
     * Set an option for the drawing group.
     *
     * @param int $property The number specifies the option
     */
    public function setOPT(int $property, mixed $value): void
    {
        $this->OPT[$property] = $value;

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Re-save the workbook in Excel/LibreOffice (which rebuilds consistent Escher) or convert to .xlsx
  2. If images are unnecessary, convert to CSV or a drawing-free format before processing
  3. Catch the exception in batch readers and quarantine the file
  4. Update PhpSpreadsheet to benefit from reader hardening
Defensive patterns

Strategy: try-catch

Validate before calling

// If images are not required, read without them to sidestep Bstore dereference
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
$reader->setReadDataOnly(true); // skips drawing/image processing
$spreadsheet = $reader->load($path);

Try / catch

try {
    $spreadsheet = (new \PhpOffice\PhpSpreadsheet\Reader\Xls())->load($path);
} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
    if (str_contains($e->getMessage(), 'bstoreContainer')) {
        $spreadsheet = (new \PhpOffice\PhpSpreadsheet\Reader\Xls())
            ->setReadDataOnly(true)
            ->load($path);
    }
}

Prevention

When it happens

Trigger: Reading an .xls where sheet-level Escher references images but the workbook-level Dgg container has no Bstore container (images referenced yet never stored) — inconsistent Escher produced by broken writers or corruption.

Common situations: Legacy .xls files from non-Excel tools that emit image references without the store; files processed by tools that dropped OLE streams; archived reports.

Related errors


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