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

Quantization levels value must be between 1 and 256

Error message

Quantization levels value must be between 1 and 256

What it means

Palette::quantize() and Palette::reduce() both delegate to the private quantizeColor(), which maps each color channel onto a fixed number of discrete levels. The binning math only works for 1 to 256 levels (256 equals one level per 8-bit step), so any other integer (0, negative, or above 256) throws InvalidArgumentException before any color is processed.

Source

Thrown at src/Colors/Palette.php:458

    /**
     * {@inheritdoc}
     *
     * @see PaletteInterface::hasColor()
     */
    public function hasColor(ColorInterface $color): bool
    {
        return array_key_exists($this->hashColor($color), $this->bins);
    }

    /**
     * Quantize given color to number of levels.
     *
     * @throws InvalidArgumentException
     */
    private function quantizeColor(ColorInterface $color, int $levels): ColorInterface
    {
        if ($levels < 1 || $levels > 256) {
            throw new InvalidArgumentException('Quantization levels value must be between 1 and 256');
        }

        // preserve alpha unquantized
        $alpha = $color->alpha()->normalized();

        // normalized channel values
        $normalized = array_map(
            fn(ColorChannelInterface $channel): float => $channel->normalized(),
            $color->channels(),
        );

        // normalized channel values to bin index
        $quantized = array_map(
            function (float $normalized) use ($levels): int {
                $bin = (int) floor($normalized * $levels); // 1.0 belongs to the last bin.
                return min($bin, $levels - 1);
            },
            $normalized,

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Clamp the value before calling: $levels = max(1, min(256, $levels))
  2. Validate user/config input against the 1..256 range and reject early with your own error
  3. If you meant 'keep only N dominant colors', use $palette->sortByPresence()->slice(0, N) instead of quantize()

Example fix

// before
$palette->quantize($request->integer('levels')); // 0 or 300 passed by user

// after
$levels = max(1, min(256, $request->integer('levels')));
$palette->quantize($levels);
Defensive patterns

Strategy: validation

Validate before calling

$levels = max(1, min(256, (int) $input));
if ($levels < 1 || $levels > 256) {
    throw new \OutOfRangeException('levels must be 1..256');
}
$palette->quantize($levels);

Try / catch

try {
    $palette->quantize($levels);
} catch (\Intervention\Image\Exceptions\InvalidArgumentException $e) {
    $palette->quantize(16); // retry with a known-safe level count
}

Prevention

When it happens

Trigger: $palette->quantize(0), $palette->quantize(257), $palette->reduce(-1), or passing a computed level count such as count($colors) + 300 without clamping.

Common situations: Exposing the level value to end users or a config file without bounds checking; off-by-one loops like for ($i = 0; $i <= 257; $i++); confusing 'reduce the palette to N colors' (use sortByPresence() + slice()) with 'quantize to N levels'.

Related errors


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