PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

imagettfbbox failed

Error message

imagettfbbox failed

What it means

Thrown by Font::getTextWidthPixelsExact() when PHP's GD function imagettfbbox() returns false while measuring rendered text width. This method is only used for the 'exact' column auto-size mode (Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT)); the default 'approx' mode never calls GD. The failure almost always means the resolved TrueType font file could not be parsed by FreeType, or the GD extension lacks usable FreeType support.

Source

Thrown at src/PhpSpreadsheet/Shared/Font.php:434

        // Convert from pixel width to column width
        $columnWidth = Drawing::pixelsToCellDimension((int) $columnWidth, $defaultFont ?? new FontStyle());

        // Return
        return round($columnWidth, 4);
    }

    /**
     * Get GD text width in pixels for a string of text in a certain font at a certain rotation angle.
     */
    public static function getTextWidthPixelsExact(string $text, FontStyle $font, int $rotation = 0): float
    {
        // font size should really be supplied in pixels in GD2,
        // but since GD2 seems to assume 72dpi, pixels and points are the same
        $fontFile = self::getTrueTypeFontFileFromFont($font);
        $textBox = imagettfbbox($font->getSize() ?? 10.0, $rotation, $fontFile, $text);
        if ($textBox === false) {
            // @codeCoverageIgnoreStart
            throw new PhpSpreadsheetException('imagettfbbox failed');
            // @codeCoverageIgnoreEnd
        }

        // Get corners positions
        /** @var int[] $textBox */
        $lowerLeftCornerX = $textBox[0];
        $lowerRightCornerX = $textBox[2];
        $upperRightCornerX = $textBox[4];
        $upperLeftCornerX = $textBox[6];

        // Consider the rotation when calculating the width
        return round(max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX), 4);
    }

    /**
     * Get approximate width in pixels for a string of text in a certain font at a certain rotation angle.
     *
     * @return int Text width in pixels (no padding added)

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Check GD capabilities: var_dump(gd_info()) and confirm ['FreeType Support'] => true; if missing, reinstall/enable php-gd compiled with FreeType (e.g. apt install libfreetype6-dev + rebuild, or use an image that bundles it).
  2. Verify the exact TTF file being used: inspect Font::getTrueTypeFontPath() and the file getTrueTypeFontFileFromFont() resolves for the cell font; open that .ttf with fontforge/fc-query to confirm it is a valid TrueType font readable by the web server user.
  3. Point Font::setTrueTypeFontPath() to a directory of known-good .ttf files (e.g. a copy of the Calibri/Arial files you actually use) and make sure the font name set on cells maps to a real variant (bold/italic files present).
  4. If exact measurement is not required, stay with the default: Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_APPROX) — it uses an approximation and never touches GD.

Example fix

// before
Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT);
$sheet->getColumnDimension('A')->setAutoSize(true);
$writer->save('out.xlsx'); // imagettfbbox failed

// after
if (function_exists('gd_info') && (gd_info()['FreeType Support'] ?? false)) {
    Font::setTrueTypeFontPath('/var/www/fonts'); // dir with valid .ttf files
    Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT);
} else {
    Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_APPROX);
}
Defensive patterns

Strategy: fallback

Validate before calling

$info = function_exists('gd_info') ? gd_info() : [];
$canExact = ($info['FreeType Support'] ?? false)
    && is_dir(\PhpOffice\PhpSpreadsheet\Shared\Font::getTrueTypeFontPath());
\PhpOffice\PhpSpreadsheet\Shared\Font::setAutoSizeMethod(
    $canExact ? Font::AUTOSIZE_METHOD_EXACT : Font::AUTOSIZE_METHOD_APPROX
);

Try / catch

try {
    $writer->save($path); // exact autosize runs here
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    if (str_contains($e->getMessage(), 'imagettfbbox')) {
        \PhpOffice\PhpSpreadsheet\Shared\Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_APPROX);
        $writer->save($path); // retry without GD
    } else { throw $e; }
}

Prevention

When it happens

Trigger: Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT) followed by enabling $sheet->getColumnDimension('X')->setAutoSize(true) and saving via any writer; calculateColumnWidth() routes to getTextWidthPixelsExact(), which calls getTrueTypeFontFileFromFont() and then imagettfbbox(). It fails when the TTF file at the resolved path is corrupt/empty/not a real TTF, when the file is unreadable by the PHP process, or when GD is compiled without FreeType.

Common situations: Deploying to a slim Docker/alpine image where the GD extension has no freetype support; pointing Font::setTrueTypeFontPath() at a directory with placeholder or zero-byte font files; a font name that maps to a file that exists but is actually a collection/OTF/var-font FreeType cannot open in this build; upgrading PHP/GD versions that drop FreeType.

Related errors


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