Intervention/image · error · StateException

The text color must be fully opaque when using the stroke ef

Error message

The text color must be fully opaque when using the stroke effect

What it means

StateException from the Imagick text modifier: when the font has a stroke effect enabled, the text fill color must be fully opaque. The check decodes the configured color and rejects any transparent value before it is exported to an Imagick pixel value, because a transparent fill under a stroke outline produces broken output in ImageMagick's renderer.

Source

Thrown at src/Drivers/Imagick/Modifiers/TextModifier.php:70

            }
        }

        return $image;
    }

    /**
     * Create an ImagickDraw object to draw text on the image
     *
     * @throws StateException
     * @throws DriverException
     * @throws RuntimeException
     */
    private function imagickDrawText(ImageInterface $image, FontInterface $font): ImagickDraw
    {
        $color = $this->driver()->decodeColor($font->color());

        if ($font->hasStrokeEffect() && $color->isTransparent()) {
            throw new StateException(
                'The text color must be fully opaque when using the stroke effect',
            );
        }

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

        return $this->processor()->toImagickDraw($font, $color);
    }

    /**
     * Create a ImagickDraw object to draw the outline stroke effect on the Image
     *
     * @throws StateException
     * @throws DriverException
     * @throws RuntimeException
     */
    private function imagickDrawStroke(ImageInterface $image, FontInterface $font): ?ImagickDraw
    {

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Use a fully opaque text color (e.g. '#ffffff' or 'rgba(255,255,255,1)') when a stroke effect is set
  2. Drop the stroke effect if transparent text is intentional
  3. Draw the text on a separate layer with the desired opacity and blend the layer instead of using alpha on the fill

Example fix

// before
$image->text('watermark', 10, 10, fn ($font) => $font
    ->color('rgba(255,255,255,0.4)')
    ->stroke('000000', 1)
);

// after
$image->text('watermark', 10, 10, fn ($font) => $font
    ->color('#ffffff')
    ->stroke('000000', 1)
);
Defensive patterns

Strategy: validation

Validate before calling

// only pair a stroke effect with fully opaque hex fill colors
if ($strokeWidth > 0 && !preg_match('/^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i', $textColor)) {
    throw new InvalidArgumentException(
        'Text color must be fully opaque (e.g. #ffffff) when using a stroke effect'
    );
}
$image->text($caption, $x, $y, fn ($font) => $font->color($textColor)->stroke($strokeColor, $strokeWidth));

Type guard

function isOpaqueHexColor(string $color): bool
{
    return (bool) preg_match('/^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i', $color);
}

Try / catch

use Intervention\Image\Exceptions\StateException;

try {
    $image->text($caption, $x, $y, $fontCallback);
} catch (StateException $e) {
    // configuration bug - fix the color config, do not retry
    throw new InvalidArgumentException('Invalid text config: ' . $e->getMessage(), 0, $e);
}

Prevention

When it happens

Trigger: $image->text('label', $x, $y, fn ($font) => $font->color('rgba(255,255,255,0)')->stroke('000', 1)) - any text color with alpha below 1 (including 'transparent' or 8-digit hex with 00 alpha) combined with a stroke effect.

Common situations: Porting watermark/label styles from CSS where semi-transparent text plus an outline is common; reusing a palette color that carries alpha for text; config presets that always set a stroke width even when the color is meant to be see-through.

Related errors


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