Intervention/image · error · StateException
No font file specified
Error message
No font file specified
What it means
toImagickDraw() throws StateException 'No font file specified' when the Font object has no file attached (src/Drivers/Imagick/FontProcessor.php:61-63). The Imagick driver has no built-in fallback font, so every text() or boxSize() call must supply a font file via the font closure. This is a pure usage error thrown before any ImageMagick call — nothing environmental.
Source
Thrown at src/Drivers/Imagick/FontProcessor.php:62
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
{
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
- Add ->file($path) inside the font closure of your text() call
- Use an absolute path to a font you ship with the app (e.g. base_path('fonts/Inter-Regular.ttf'))
- Verify at runtime: is_readable($path) before calling text()
- Do not rely on system font paths that differ between dev, CI, and production
Example fix
// before
$image->text('Hello', 100, 100, function ($font) {
$font->size(24);
});
// after
$image->text('Hello', 100, 100, function ($font) {
$font->file(base_path('fonts/Inter-Regular.ttf'));
$font->size(24);
}); Defensive patterns
Strategy: validation
Validate before calling
$fontFile = realpath(__DIR__ . '/fonts/Inter-Regular.ttf');
if ($fontFile === false || !is_readable($fontFile)) {
throw new RuntimeException('Font file missing: ' . $fontFile);
}
// ->file() is what prevents the StateException
$image->text('Hello', 100, 100, fn ($font) => $font->file($fontFile)); Type guard
// If you build Font objects yourself
if (!method_exists($font, 'hasFile') || !$font->hasFile()) {
throw new RuntimeException('Font has no file; Imagick driver requires one');
} Try / catch
use Intervention\Image\Exceptions\StateException;
try {
$image->text($label, $x, $y, fn ($font) => $font->file($this->fontPath)->size(20));
} catch (StateException $e) {
// usage bug: font file not set — fix the closure, do not retry
throw new LogicException('text() requires ->file() on the Imagick driver', 0, $e);
} Prevention
- Always set ->file() in the font closure; treat it as required on the Imagick driver
- Keep fonts inside the repo and reference absolute paths
- Assert in tests that your text helper includes a font file
When it happens
Trigger: Calling $image->text('Hello', $x, $y, fn ($font) => $font->size(24)->color('f00')) without ->file(...); building an Intervention\Image\Typography\Font manually and never calling setFilepath() before boxSize()/toImagickDraw().
Common situations: Copy-pasting GD examples or Intervention Image v2 snippets where a default font existed; assuming a system default font is used; the font file argument simply forgotten during refactoring.
Related errors
- The text color must be fully opaque when using the stroke ef
- The stroke color must be fully opaque
- Failed query font metrics
- Failed to convert font to ImagickDraw instance
- 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/626fac71e285da8d.
Report an issue: GitHub.