Intervention/image · error · DriverException
Failed to convert font to ImagickDraw instance
Error message
Failed to convert font to ImagickDraw instance
What it means
While converting the Font into an ImagickDraw — setStrokeAntialias, setTextAntialias, setFont($font->filepath()), setFontSize, setTextAlignment, setFillColor (src/Drivers/Imagick/FontProcessor.php:66-75) — any ImagickException or ImagickDrawException is wrapped as DriverException. In practice setFont() fails when the file path does not exist, is unreadable, or is not a loadable font, so ImageMagick cannot open the font resource.
Source
Thrown at src/Drivers/Imagick/FontProcessor.php:77
public function toImagickDraw(FontInterface $font, ?ImagickPixel $color = null): ImagickDraw
{
if (!$font->hasFile()) {
throw new StateException('No font file specified');
}
try {
$draw = new ImagickDraw();
$draw->setStrokeAntialias(true);
$draw->setTextAntialias(true);
$draw->setFont($font->filepath());
$draw->setFontSize($this->nativeFontSize($font));
$draw->setTextAlignment(Imagick::ALIGN_LEFT);
if ($color instanceof ImagickPixel) {
$draw->setFillColor($color);
}
} catch (ImagickException | ImagickDrawException $e) {
throw new DriverException('Failed to convert font to ImagickDraw instance', previous: $e);
}
return $draw;
}
}
View on GitHub (pinned to 5598b9e397)
Solutions
- Use absolute paths for font files and verify with is_readable() before calling text()
- Fix permissions for the runtime user (www-data, queue-worker) on the fonts directory
- Confirm the file is really a font: file command, fc-scan, or finfo mime type
- Exclude the fonts path from open_basedir restrictions if applicable
Example fix
// before
$fontPath = 'fonts/arial.ttf'; // relative, breaks in other cwd
$image->text($label, 50, 50, fn ($font) => $font->file($fontPath));
// after
$fontPath = realpath(__DIR__ . '/fonts/arial.ttf');
if ($fontPath === false || !is_readable($fontPath)) {
throw new RuntimeException('Font file missing or unreadable');
}
$image->text($label, 50, 50, fn ($font) => $font->file($fontPath)); Defensive patterns
Strategy: validation
Validate before calling
if (!is_string($fontPath) || !is_readable($fontPath)) {
throw new RuntimeException('Cannot read font file: ' . print_r($fontPath, true));
}
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($fontPath);
if (!str_starts_with($mime, 'font/')) {
throw new RuntimeException('Not a font file (mime ' . $mime . ')');
}
$image->text($label, $x, $y, fn ($font) => $font->file($fontPath)); Try / catch
use Intervention\Image\Exceptions\DriverException;
try {
$image->text($label, $x, $y, fn ($font) => $font->file($fontPath));
} catch (DriverException $e) {
$reason = $e->getPrevious()?->getMessage() ?? '';
if (str_contains($reason, 'UnableToOpenFont') || str_contains(strtolower($reason), 'font')) {
throw new RuntimeException('Font failed to load from ' . $fontPath . ': ' . $reason, 0, $e);
}
throw $e;
} Prevention
- Resolve font paths with realpath() at boot and cache the result
- Make fonts readable by the PHP runtime user in Docker (COPY --chmod) and deploy scripts
- Check finfo mime of uploaded fonts before storing them
When it happens
Trigger: text()/boxSize() with $font->file() pointing to a missing, moved, or permission-denied file; a file that exists but is not a font (mislabeled .ttf); open_basedir restrictions blocking the font location; temp font files deleted before use.
Common situations: Relative font paths that break when the working directory changes (queue workers, CLI, cron); fonts under storage/ not readable by www-data; deployment pipelines that skip the fonts directory; downloaded fonts truncated.
Related errors
- Failed query font metrics
- No font file specified
- The text color must be fully opaque when using the stroke ef
- The stroke color must be fully opaque
- Failed to apply ' . self::class . ', unable to draw text lin
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/3cd02b4eacd65114.
Report an issue: GitHub.