PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Valid directory to TrueType Font files not specified
Error message
Valid directory to TrueType Font files not specified
What it means
Thrown by Font::getTrueTypeFontFileFromFont() when it needs to resolve a TrueType file but the static font directory is empty or does not exist. The library ships no font files, so the directory defaults to '' and exact text measurement cannot work until you supply one. Only code paths that measure text with GD (the 'exact' auto-size method) reach this check.
Source
Thrown at src/PhpSpreadsheet/Shared/Font.php:544
*
* @param float|int $sizeInCm Font size (in centimeters)
*
* @return float Size (in pixels)
*/
public static function centimeterSizeToPixels(int|float $sizeInCm): float
{
return $sizeInCm * 37.795275591;
}
/**
* Returns the font path given the font.
*
* @return string Path to TrueType font file
*/
public static function getTrueTypeFontFileFromFont(FontStyle $font, bool $checkPath = true): string
{
if ($checkPath && (!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath))) {
throw new PhpSpreadsheetException('Valid directory to TrueType Font files not specified');
}
$name = $font->getName();
$fontArray = array_merge(self::FONT_FILE_NAMES, self::$extraFontArray);
if (!isset($fontArray[$name])) {
throw new PhpSpreadsheetException('Unknown font name "' . $name . '". Cannot map to TrueType font file');
}
$bold = $font->getBold();
$italic = $font->getItalic();
$index = 'x';
if ($bold) {
$index .= 'b';
}
if ($italic) {
$index .= 'i';
}
$fontFile = $fontArray[$name][$index];
View on GitHub (pinned to 65b080eef4)
Solutions
- Call Font::setTrueTypeFontPath('/absolute/path/to/fonts') early (bootstrap), pointing at a real directory containing the .ttf files for the fonts your sheets use.
- Use an absolute path (e.g. via the project root constant) rather than a relative one so the check survives changes of current working directory.
- Verify with is_dir(Font::getTrueTypeFontPath()) in a startup assertion, and ship the fonts directory in your deployment artifact.
- If you do not need GD-accurate widths, keep Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_APPROX) (the default) and this code path is never entered.
Example fix
// before
Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT);
$writer->save('out.xlsx'); // Valid directory to TrueType Font files not specified
// after
Font::setTrueTypeFontPath(dirname(__DIR__) . '/resources/fonts');
Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT); Defensive patterns
Strategy: validation
Validate before calling
$dir = \PhpOffice\PhpSpreadsheet\Shared\Font::getTrueTypeFontPath();
if ($dir === '' || !is_dir($dir) || !is_readable($dir)) {
\PhpOffice\PhpSpreadsheet\Shared\Font::setTrueTypeFontPath($appRoot . '/resources/fonts');
}
assert(is_dir(\PhpOffice\PhpSpreadsheet\Shared\Font::getTrueTypeFontPath())); Try / catch
try { $writer->save($path); }
catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
if (str_contains($e->getMessage(), 'TrueType Font files not specified')) {
\PhpOffice\PhpSpreadsheet\Shared::class; // configure fonts then retry
\PhpOffice\PhpSpreadsheet\Shared\Font::setTrueTypeFontPath($fallbackDir);
$writer->save($path);
} else { throw $e; }
} Prevention
- Set Font::setTrueTypeFontPath() once in bootstrap with an absolute path; never rely on the empty default when exact autosize is on.
- Assert the fonts directory exists during smoke tests/deploy checks so a missing mount fails loudly at startup, not at export time.
When it happens
Trigger: Calling Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT) and triggering column auto-sizing on save without ever calling Font::setTrueTypeFontPath($dir); or calling Font::getTrueTypeFontFileFromFont($font) directly (it defaults to $checkPath = true). The check is `!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath)`, so an empty string, a file path, or a deleted/renamed directory all throw.
Common situations: Enabling exact auto-size after copying code from documentation that assumes fonts are bundled; setting a path relative to the old CWD that breaks when the app runs from a different directory or under cron/queue workers; the fonts directory being absent in a Docker build (excluded by .dockerignore).
Related errors
- Unknown font name "$name". Cannot map to TrueType font file
- imagettfbbox failed
- TrueType Font file not found
- Invalid value $calculateDateTimeType for calculated date tim
- Invalid timezone {$timezoneName}
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/655f05c35c64ba8a.
Report an issue: GitHub.