{"record":{"id":"2d5ca8b4ddf8ea32","repo":"PHPOffice/PhpSpreadsheet","slug":"dggcontainer-is-unexpectedly-null","errorCode":null,"errorMessage":"dggContainer is unexpectedly null","messagePattern":"dggContainer is unexpectedly null","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Shared/Escher.php","lineNumber":32,"sourceCode":"    /**\n     * Drawing Container.\n     */\n    private ?Escher\\DgContainer $dgContainer = null;\n\n    /**\n     * Get Drawing Group Container.\n     */\n    public function getDggContainer(): ?Escher\\DggContainer\n    {\n        return $this->dggContainer;\n    }\n\n    /**\n     * Get Drawing Group Container.\n     */\n    public function getDggContainerOrThrow(): Escher\\DggContainer\n    {\n        return $this->dggContainer ?? throw new SpreadsheetException('dggContainer is unexpectedly null');\n    }\n\n    /**\n     * Set Drawing Group Container.\n     */\n    public function setDggContainer(Escher\\DggContainer $dggContainer): Escher\\DggContainer\n    {\n        return $this->dggContainer = $dggContainer;\n    }\n\n    /**\n     * Get Drawing Container.\n     */\n    public function getDgContainer(): ?Escher\\DgContainer\n    {\n        return $this->dgContainer;\n    }\n","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Shared/Escher.php#L14-L50","documentation":"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.","triggerScenarios":"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.","commonSituations":"Enterprise report archives processed in batch; files that survived partial transfers; workbooks from non-Excel writers with incomplete Escher implementations.","solutions":["Re-save the workbook in Excel or LibreOffice (open + save) to rebuild a complete Escher structure, or convert to .xlsx","Strip drawings before processing if images are irrelevant: convert to CSV/xlsx without images","Catch the exception around load and quarantine/reject the specific file in batch pipelines","Update PhpSpreadsheet — these OrThrow accessors replaced silent null handling, and reader robustness improves across releases"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check file integrity before the reader dereferences Escher containers\n$zipCheck = true; // OLE2 files: verify size > 0 and signature\n$fh = fopen($path, 'rb');\n$sig = fread($fh, 8);\nfclose($fh);\nif ($sig !== \"\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1\") {\n    $zipCheck = false;\n}\nif (!$zipCheck) {\n    throw new InvalidArgumentException('Not a valid .xls workbook');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $spreadsheet = $reader->load($path);\n} catch (\\PhpOffice\\PhpSpreadsheet\\Reader\\Exception $e) {\n    if (str_contains($e->getMessage(), 'dggContainer')) {\n        // malformed Escher drawing group: route to repair/re-save pipeline\n    }\n}","preventionTips":["Re-save legacy drawing-heavy .xls files via LibreOffice at ingest","Quarantine files whose Escher structures are incomplete instead of retrying","Keep the library updated for reader hardening"],"tags":["xls","escher","drawings","corrupt-file"],"backgroundTag":"unexpected-null-property","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}