{"record":{"id":"37906b805263d604","repo":"PHPOffice/PhpSpreadsheet","slug":"unexpected-null-font","errorCode":null,"errorMessage":"unexpected null font","messagePattern":"unexpected null font","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/RichText/Run.php","lineNumber":38,"sourceCode":"    public function __construct(string $text = '')\n    {\n        parent::__construct($text);\n        // Initialise variables\n        $this->font = new Font();\n    }\n\n    /**\n     * Get font.\n     */\n    public function getFont(): ?Font\n    {\n        return $this->font;\n    }\n\n    public function getFontOrThrow(): Font\n    {\n        if ($this->font === null) {\n            throw new SpreadsheetException('unexpected null font');\n        }\n\n        return $this->font;\n    }\n\n    /**\n     * Set font.\n     *\n     * @param ?Font $font Font\n     *\n     * @return $this\n     */\n    public function setFont(?Font $font = null): static\n    {\n        $this->font = $font;\n\n        return $this;\n    }","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/RichText/Run.php#L20-L56","documentation":"RichText\\Run::getFontOrThrow() returns the run's Font or throws when it is null. The constructor always assigns a default Font (src/PhpSpreadsheet/RichText/Run.php:24), so null can only appear after setFont(null) — setFont accepts ?Font — or in a subclass that bypasses the constructor. The OrThrow variant exists so code that genuinely requires a font (writers, renderers) can fail loudly instead of silently mishandling null.","triggerScenarios":"Creating a Run, calling setFont(null) (often to mimic inheritance from the cell font), then calling getFontOrThrow(); assembling rich text via setRichTextElements() with hand-built runs whose fonts were nulled; passing such a Run to export code that calls getFontOrThrow().","commonSituations":"Code that nulls run fonts to 'inherit' the base font before export, then hits a writer needing a concrete font; refactors from getFont() (nullable tolerated) to getFontOrThrow(); partial deserialization of rich text from JSON.","solutions":["Use the nullable accessor with a fallback: $run->getFont() ?? new Font()","Stop calling setFont(null); keep the default font or explicitly set a Font instance","If a run's font was nulled by upstream code, re-create the Run (its constructor installs a default Font)"],"exampleFix":"// before\n$run->setFont(null);\n$font = $run->getFontOrThrow(); // throws: unexpected null font\n\n// after\n$font = $run->getFont() ?? new \\PhpOffice\\PhpSpreadsheet\\Style\\Font();","handlingStrategy":"type-guard","validationCode":"$run = new \\PhpOffice\\PhpSpreadsheet\\RichText\\Run('text');\n$run->setFont(null); // if this must stay, use getFont() downstream","typeGuard":"function runHasFont(\\PhpOffice\\PhpSpreadsheet\\RichText\\Run $run): bool\n{\n    return $run->getFont() !== null;\n}\n\n// usage\n$font = $run->getFont() ?? new \\PhpOffice\\PhpSpreadsheet\\Style\\Font();","tryCatchPattern":"try {\n    $font = $run->getFontOrThrow();\n} catch (\\PhpOffice\\PhpSpreadsheet\\Exception $e) {\n    $font = new \\PhpOffice\\PhpSpreadsheet\\Style\\Font(); // sensible default\n}","preventionTips":["Treat run fonts as nullable in your own code; use getFont() unless non-null is guaranteed","Never setFont(null) before export flows that need a concrete font","Rebuild runs (constructor installs a default Font) instead of nulling"],"tags":["richtext","nullable","font-style"],"backgroundTag":"unexpected-null-property","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}