Intervention/image · error · Intervention\Image\Exceptions\InvalidArgumentException

Normalized color channel value must be between 0 to 1

Error message

Normalized color channel value must be between 0 to 1

What it means

FloatColorChannel::fromNormalized() maps a value in the closed interval [0.0, 1.0] onto the channel's internal range, and rejects anything outside it. This is the base factory for float channels such as alpha, so the check fires whenever a 'normalized' value is actually a percentage (e.g. 50 instead of 0.5), a negative number, or a float that drifted slightly past 1.0 through arithmetic.

Source

Thrown at src/Colors/FloatColorChannel.php:29

    /**
     * @throws InvalidArgumentException
     */
    final public function __construct(float $value)
    {
        $this->value = (float) $this->validValueOrFail($value);
    }

    /**
     * {@inheritdoc}
     *
     * @see ColorChannelInterface::fromNormalized()
     *
     * @throws InvalidArgumentException
     */
    public static function fromNormalized(float $normalized): self
    {
        if ($normalized < 0 || $normalized > 1) {
            throw new InvalidArgumentException(
                'Normalized color channel value must be between 0 to 1',
            );
        }

        return new static(static::min() + $normalized * (static::max() - static::min()));
    }

    /**
     * {@inheritdoc}
     *
     * @see ColorChannelInterface::value()
     */
    public function value(): float
    {
        return (float) $this->value;
    }
}

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Divide percentages by 100 before calling fromNormalized()
  2. Clamp before calling: $value = min(1.0, max(0.0, $value))
  3. Guard division: if ($total <= 0) { $ratio = 0.0; } else { $ratio = $part / $total; }
  4. Round tiny float artifacts: $value = round($value, 6) before the call

Example fix

// before
$alpha = Alpha::fromNormalized($userOpacity * 100); // 0-100 scale passed as normalized

// after
$alpha = Alpha::fromNormalized($userOpacity); // already 0.0-1.0
// or convert explicitly:
$alpha = Alpha::fromNormalized($percent / 100);
Defensive patterns

Strategy: validation

Validate before calling

$normalized = min(1.0, max(0.0, $normalized));
if (!is_finite($normalized)) {
    $normalized = 0.0;
}
$channel = Alpha::fromNormalized($normalized);

Type guard

function isNormalizedValue(mixed $value): bool
{
    return is_float($value) && is_finite($value) && $value >= 0.0 && $value <= 1.0;
}

Prevention

When it happens

Trigger: Calling Alpha::fromNormalized(50) after forgetting to divide a percentage by 100; passing a ratio computed as $part / $total when $total is 0 (gives NAN) or when the parts sum to more than the total (ratio > 1); accumulating float rounding like 0.1 + 0.2 * 5 yielding 1.0000000000000002.

Common situations: Mixing up percent (0-100) and normalized (0-1) scales when bridging UI sliders, database values, or CSS percentages into the library; unvalidated external input; statistical normalization code where sums can exceed the divisor due to rounding.

Related errors


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