Intervention/image · error · StateException

The stroke color must be fully opaque

Error message

The stroke color must be fully opaque

What it means

The GD driver fakes a text stroke by drawing the text repeatedly at pixel offsets in the stroke color beneath the real text, so a semi-transparent stroke would bleed through the glyphs and break the effect. gdStrokeColor() therefore rejects any stroke color whose alpha is below fully opaque (isTransparent() is true for any alpha < 1) with StateException, but only when a stroke effect is active (strokeWidth > 0). Defaults are opaque ('ffffff' stroke, '000000' text), so the error requires an explicitly transparent stroke color; the Imagick driver renders alpha strokes natively and does not throw.

Source

Thrown at src/Drivers/Gd/Modifiers/TextModifier.php:143

            ->colorProcessor($image)
            ->export(parent::textColor());
    }

    /**
     * Decode color for stroke (outline) effect in GD compatible format
     *
     * @throws StateException
     */
    protected function gdStrokeColor(ImageInterface $image): int
    {
        if (!$this->font->hasStrokeEffect()) {
            return 0;
        }

        $color = parent::strokeColor();

        if ($color->isTransparent()) {
            throw new StateException('The stroke color must be fully opaque');
        }

        return $this
            ->driver()
            ->colorProcessor($image)
            ->export($color);
    }

    /**
     * Return GD's internal font size
     */
    private function gdFont(): int
    {
        if (!in_array($this->font->size(), range(1, 5))) {
            return 1;
        }

        return (int) $this->font->size();

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Use a fully opaque stroke color: '#ffffff', 'rgb(255, 255, 255)' or an Rgb\Color with alpha 1
  2. Drop the stroke effect (strokeWidth 0) when transparency is the goal
  3. Pre-blend the intended color against the known background to get an opaque equivalent
  4. Switch to the Imagick driver if alpha strokes are a hard requirement

Example fix

// before
$image->text('Draft', 40, 40, fn($font) => $font
    ->file('arial.ttf')
    ->stroke('rgba(255,255,255,0.5)', 2));

// after: fully opaque stroke color
$image->text('Draft', 40, 40, fn($font) => $font
    ->file('arial.ttf')
    ->stroke('#ffffff', 2));
Defensive patterns

Strategy: validation

Validate before calling

use Intervention\Image\Colors\Rgb\Color as RgbColor;

$stroke = 'rgba(255,255,255,0.5)';

if ($font->strokeWidth() > 0) {
    $color = RgbColor::parse($stroke); // hex / rgb() / rgba() / named strings

    if ($color->isTransparent()) {
        throw new RuntimeException(
            'GD requires a fully opaque stroke color; use e.g. #ffffff instead'
        );
    }
}

$image->text('Draft', 40, 40, $font);

Try / catch

use Intervention\Image\Exceptions\StateException;

try {
    $image->text('Draft', 40, 40, $font);
} catch (StateException $e) {
    // retry with a fully opaque stroke color
    $font->setStrokeColor('#ffffff');
    $image->text('Draft', 40, 40, $font);
}

Prevention

When it happens

Trigger: $image->text(...) with fn($font) => $font->stroke('rgba(255,255,255,0.5)', 2); a stroke color of 'transparent' or any ColorInterface with alpha < 1 while strokeWidth > 0; typography code written against the Imagick driver then run under GD.

Common situations: Design systems specifying rgba() outline colors; theme color tokens with alpha reused for captions and watermarks; driver-agnostic code tested only with Imagick.

Related errors


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