PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
unexpected null font
Error message
unexpected null font
What it means
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.
Source
Thrown at src/PhpSpreadsheet/RichText/Run.php:38
public function __construct(string $text = '')
{
parent::__construct($text);
// Initialise variables
$this->font = new Font();
}
/**
* Get font.
*/
public function getFont(): ?Font
{
return $this->font;
}
public function getFontOrThrow(): Font
{
if ($this->font === null) {
throw new SpreadsheetException('unexpected null font');
}
return $this->font;
}
/**
* Set font.
*
* @param ?Font $font Font
*
* @return $this
*/
public function setFont(?Font $font = null): static
{
$this->font = $font;
return $this;
}View on GitHub (pinned to 65b080eef4)
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)
Example fix
// before $run->setFont(null); $font = $run->getFontOrThrow(); // throws: unexpected null font // after $font = $run->getFont() ?? new \PhpOffice\PhpSpreadsheet\Style\Font();
Defensive patterns
Strategy: type-guard
Validate before calling
$run = new \PhpOffice\PhpSpreadsheet\RichText\Run('text');
$run->setFont(null); // if this must stay, use getFont() downstream Type guard
function runHasFont(\PhpOffice\PhpSpreadsheet\RichText\Run $run): bool
{
return $run->getFont() !== null;
}
// usage
$font = $run->getFont() ?? new \PhpOffice\PhpSpreadsheet\Style\Font(); Try / catch
try {
$font = $run->getFontOrThrow();
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
$font = new \PhpOffice\PhpSpreadsheet\Style\Font(); // sensible default
} Prevention
- 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
When it happens
Trigger: 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().
Common situations: 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.
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/37906b805263d604.
Report an issue: GitHub.