Intervention/image · error · DriverException

Failed query font metrics

Error message

Failed query font metrics

What it means

FontProcessor::boxSize() measures text via (new Imagick())->queryFontMetrics($draw, $text) and wraps any ImagickException as DriverException. ImageMagick's text rendering requires a valid UTF-8 string and a loadable font, so the dominant real-world causes are byte-invalid UTF-8 text (sequences cut mid-character) or a font file ImageMagick cannot actually read. The native error is on getPrevious().

Source

Thrown at src/Drivers/Imagick/FontProcessor.php:42

     *
     * @see FontProcessorInterface::boxSize()
     *
     * @throws InvalidArgumentException
     * @throws StateException
     * @throws DriverException
     */
    public function boxSize(string $text, FontInterface $font): SizeInterface
    {
        // no text - no box size
        if (mb_strlen($text) === 0) {
            return new Size(0, 0);
        }

        $draw = $this->toImagickDraw($font);
        try {
            $dimensions = (new Imagick())->queryFontMetrics($draw, $text);
        } catch (ImagickException $e) {
            throw new DriverException('Failed query font metrics', previous: $e);
        }

        return new Size(
            intval(round($dimensions['textWidth'])),
            intval(round($dimensions['ascender'] + $dimensions['descender'])),
        );
    }

    /**
     * Imagick::annotateImage() needs an ImagickDraw object - this method takes
     * the font object as the base and adds an optional passed color to the new
     * ImagickDraw object.
     *
     * @throws StateException
     * @throws DriverException
     */
    public function toImagickDraw(FontInterface $font, ?ImagickPixel $color = null): ImagickDraw
    {

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Sanitize before drawing: $text = mb_scrub($text) (replaces invalid bytes) or mb_convert_encoding($text, 'UTF-8', 'UTF-8')
  2. Truncate with mb_substr(), never substr(), so multibyte sequences stay intact
  3. Verify the font file is readable and really a font: is_readable() plus a finfo/fc-scan check
  4. Read $e->getPrevious()->getMessage() to tell an encoding error apart from a font-loading error

Example fix

// before
$image->text($userText, 100, 100, fn ($font) => $font->file($fontFile));

// after
$text = mb_scrub($userText);
$image->text($text, 100, 100, fn ($font) => $font->file($fontFile));
Defensive patterns

Strategy: validation

Validate before calling

// Guarantee valid UTF-8 and a readable font before any text call
$text = mb_scrub($userInput);          // replace invalid bytes with U+FFFD
$text = mb_substr($text, 0, 500);      // multibyte-safe truncation
if (!is_readable($fontFile)) {
    throw new RuntimeException('Font file unreadable: ' . $fontFile);
}
$image->text($text, $x, $y, fn ($font) => $font->file($fontFile)->size(24));

Try / catch

use Intervention\Image\Exceptions\DriverException;

try {
    $size = $image->getDriver()->fontProcessor()->boxSize($text, $font);
} catch (DriverException $e) {
    $reason = $e->getPrevious()?->getMessage() ?? '';
    if (str_contains(strtolower($reason), 'utf')) {
        $text = mb_scrub($text);
        $size = $image->getDriver()->fontProcessor()->boxSize($text, $font);
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Calling $image->text() with the Imagick driver, or boxSize($text, $font) directly, with text sliced by substr() instead of mb_substr(), input in ISO-8859-1/Windows-1252 passed unconverted, binary noise, or a corrupt/non-font file attached via $font->file().

Common situations: Legacy database columns not in utf8mb4; user input truncated with substr() cutting a multibyte emoji in half; filenames or EXIF-derived strings with invalid bytes; fonts downloaded partially or mislabeled.

Related errors


AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23). Data as JSON: /api/errors/57636897f01fd5c7. Report an issue: GitHub.