{"record":{"id":"57636897f01fd5c7","repo":"Intervention/image","slug":"failed-query-font-metrics","errorCode":null,"errorMessage":"Failed query font metrics","messagePattern":"Failed query font metrics","errorType":"exception","errorClass":"DriverException","httpStatus":null,"severity":"error","filePath":"src/Drivers/Imagick/FontProcessor.php","lineNumber":42,"sourceCode":"     *\n     * @see FontProcessorInterface::boxSize()\n     *\n     * @throws InvalidArgumentException\n     * @throws StateException\n     * @throws DriverException\n     */\n    public function boxSize(string $text, FontInterface $font): SizeInterface\n    {\n        // no text - no box size\n        if (mb_strlen($text) === 0) {\n            return new Size(0, 0);\n        }\n\n        $draw = $this->toImagickDraw($font);\n        try {\n            $dimensions = (new Imagick())->queryFontMetrics($draw, $text);\n        } catch (ImagickException $e) {\n            throw new DriverException('Failed query font metrics', previous: $e);\n        }\n\n        return new Size(\n            intval(round($dimensions['textWidth'])),\n            intval(round($dimensions['ascender'] + $dimensions['descender'])),\n        );\n    }\n\n    /**\n     * Imagick::annotateImage() needs an ImagickDraw object - this method takes\n     * the font object as the base and adds an optional passed color to the new\n     * ImagickDraw object.\n     *\n     * @throws StateException\n     * @throws DriverException\n     */\n    public function toImagickDraw(FontInterface $font, ?ImagickPixel $color = null): ImagickDraw\n    {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/Intervention/image/blob/5598b9e39751c34afc5cdee84abef77f92c26f68/src/Drivers/Imagick/FontProcessor.php#L24-L60","documentation":"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().","triggerScenarios":"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().","commonSituations":"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.","solutions":["Sanitize before drawing: $text = mb_scrub($text) (replaces invalid bytes) or mb_convert_encoding($text, 'UTF-8', 'UTF-8')","Truncate with mb_substr(), never substr(), so multibyte sequences stay intact","Verify the font file is readable and really a font: is_readable() plus a finfo/fc-scan check","Read $e->getPrevious()->getMessage() to tell an encoding error apart from a font-loading error"],"exampleFix":"// before\n$image->text($userText, 100, 100, fn ($font) => $font->file($fontFile));\n\n// after\n$text = mb_scrub($userText);\n$image->text($text, 100, 100, fn ($font) => $font->file($fontFile));","handlingStrategy":"validation","validationCode":"// Guarantee valid UTF-8 and a readable font before any text call\n$text = mb_scrub($userInput);          // replace invalid bytes with U+FFFD\n$text = mb_substr($text, 0, 500);      // multibyte-safe truncation\nif (!is_readable($fontFile)) {\n    throw new RuntimeException('Font file unreadable: ' . $fontFile);\n}\n$image->text($text, $x, $y, fn ($font) => $font->file($fontFile)->size(24));","typeGuard":null,"tryCatchPattern":"use Intervention\\Image\\Exceptions\\DriverException;\n\ntry {\n    $size = $image->getDriver()->fontProcessor()->boxSize($text, $font);\n} catch (DriverException $e) {\n    $reason = $e->getPrevious()?->getMessage() ?? '';\n    if (str_contains(strtolower($reason), 'utf')) {\n        $text = mb_scrub($text);\n        $size = $image->getDriver()->fontProcessor()->boxSize($text, $font);\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Convert external input to UTF-8 at the boundary (mb_convert_encoding from the known source encoding)","Never truncate strings with substr(); use mb_substr()","Store text in utf8mb4 columns to avoid mangled retrieval"],"tags":["imagick","text","font","utf-8","encoding"],"backgroundTag":"invalid-utf8-string","analyzedSha":"5598b9e39751c34afc5cdee84abef77f92c26f68","analyzedAt":"2026-08-23T02:17:31.068Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}