Intervention/image · error · ModifierException
Failed to apply ' . self::class . ', unable to draw text lin
Error message
Failed to apply ' . self::class . ', unable to draw text line
What it means
ModifierException from the Imagick text modifier: annotateImage() threw an ImageException while drawing a single line of text. The most common root cause is an unusable font - ImagickDraw silently accepts a bad font file and the failure only surfaces when annotation runs. The original exception is attached via getPrevious().
Source
Thrown at src/Drivers/Imagick/Modifiers/TextModifier.php:128
* @throws ModifierException
*/
private function maybeDrawTextline(
FrameInterface $frame,
Line $textline,
?ImagickDraw $draw = null,
PointInterface $offset = new Point(),
): void {
if ($draw instanceof ImagickDraw) {
try {
$result = $frame->native()->annotateImage(
$draw,
$textline->position()->x() + $offset->x(),
$textline->position()->y() + $offset->y(),
$this->font->angle(),
(string) $textline,
);
} catch (ImageException $e) {
throw new ModifierException(
'Failed to apply ' . self::class . ', unable to draw text line',
previous: $e,
);
}
if ($result === false) {
throw new ModifierException(
'Failed to apply ' . self::class . ', unable to draw text line',
);
}
}
}
/**
* Return imagick font processor
*
* @throws DriverException
* @throws StateExceptionView on GitHub (pinned to 5598b9e397)
Solutions
- Verify the font path exists and is readable (is_file() + is_readable()) before calling text()
- Use an absolute path to the font file
- Test the font with ImageMagick directly or a raw Imagick script to confirm FreeType can load it
- Catch ModifierException and inspect getPrevious() for the underlying reason
Example fix
// before
$image->text('hello', 10, 50, fn ($font) => $font->filename('fonts/arial.ttf'));
// after
$fontPath = '/var/www/app/fonts/arial.ttf';
if (!is_readable($fontPath)) {
throw new RuntimeException("Font not readable: {$fontPath}");
}
$image->text('hello', 10, 50, fn ($font) => $font->filename($fontPath)); Defensive patterns
Strategy: validation
Validate before calling
if (!is_string($fontPath) || !is_file($fontPath) || !is_readable($fontPath)) {
throw new InvalidArgumentException("Font file missing or unreadable: {$fontPath}");
}
$image->text('hello', $x, $y, fn ($font) => $font->filename($fontPath)); Type guard
function isUsableFontFile(string $path): bool
{
return is_file($path) && is_readable($path) && str_ends_with(strtolower($path), '.ttf');
} Try / catch
use Intervention\Image\Exceptions\ModifierException;
try {
$image->text($line, $x, $y, $fontCallback);
} catch (ModifierException $e) {
$reason = $e->getPrevious()?->getMessage() ?? $e->getMessage();
throw new RuntimeException("Text draw failed for font {$fontPath}: {$reason}", 0, $e);
} Prevention
- Store fonts with the application and reference them by absolute path
- Check is_readable() once at bootstrap for every configured font, not per request
- Watch open_basedir restrictions when fonts live outside the web root
When it happens
Trigger: $image->text('hello', $x, $y, fn ($font) => $font->filename($fontPath)) where the font file does not exist, is unreadable (permissions, open_basedir), or is not a loadable TTF/OTF for ImageMagick's FreeType delegate; each text line is drawn individually so the throw happens per line.
Common situations: Relative font paths that resolve differently between CLI and web SAPI; font files outside the PHP open_basedir; corrupt or non-TrueType font files; servers missing the FreeType delegate in ImageMagick.
Related errors
- Failed query font metrics
- No font file specified
- Failed to convert font to ImagickDraw instance
- The text color must be fully opaque when using the stroke ef
- The stroke color must be fully opaque
AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23).
Data as JSON: /api/errors/4ebe8a73cd6b2ea1.
Report an issue: GitHub.