huggingface/transformers · error · ValueError

`axis_value` for `quanto` backend has to be one of [`0`, `-1

Error message

`axis_value` for `quanto` backend has to be one of [`0`, `-1`] but got {self.axis_value}

What it means

ValueError in QuantoQuantizedLayer.__init__ validating axis_value, the quantization axis for value tensors. Symmetric with axis_key: the quanto backend only accepts 0 (per row/token group) or -1 (per channel). Values like 1 or 2 are rejected at cache-layer construction before quantization runs.

Source

Thrown at src/transformers/cache_utils.py:811

            raise ImportError(
                "You need to install optimum-quanto in order to use KV cache quantization with optimum-quanto "
                "backend. Please install it via  with `pip install optimum-quanto`"
            )
        elif is_quanto_greater("0.2.5", accept_dev=True):
            from optimum.quanto import MaxOptimizer, qint2, qint4
        else:
            raise ImportError(
                "You need optimum-quanto package version to be greater or equal than 0.2.5 to use `QuantoQuantizedLayer`. "
            )

        if self.nbits not in [2, 4]:
            raise ValueError(f"`nbits` for `quanto` backend has to be one of [`2`, `4`] but got {self.nbits}")

        if self.axis_key not in [0, -1]:
            raise ValueError(f"`axis_key` for `quanto` backend has to be one of [`0`, `-1`] but got {self.axis_key}")

        if self.axis_value not in [0, -1]:
            raise ValueError(
                f"`axis_value` for `quanto` backend has to be one of [`0`, `-1`] but got {self.axis_value}"
            )

        self.qtype = qint4 if self.nbits == 4 else qint2
        self.optimizer = MaxOptimizer()  # hardcode as it's the only one for per-channel quantization

    def _quantize(self, tensor, axis):
        from optimum.quanto import quantize_weight

        scale, zeropoint = self.optimizer(tensor, self.qtype, axis, self.q_group_size)
        qtensor = quantize_weight(tensor, self.qtype, axis, scale, zeropoint, self.q_group_size)
        return qtensor

    def _dequantize(self, qtensor):
        return qtensor.dequantize()


class HQQQuantizedLayer(QuantizedLayer):

View on GitHub (pinned to a597f97485)

Solutions

  1. Set axis_value to 0 or -1 for the quanto backend
  2. Translate HQQ axes when migrating: HQQ 1 (channel) -> quanto -1
  3. Keep axis_key/axis_value consistent unless you intentionally want asymmetric quantization

Example fix

# before
config = QuantoQuantizedCacheConfig(nbits=4, axis_value=1, backend='quanto')

# after
config = QuantoQuantizedCacheConfig(nbits=4, axis_value=-1, backend='quanto')
Defensive patterns

Strategy: validation

Validate before calling

assert config.backend != 'quanto' or config.axis_value in (0, -1), 'quanto axis_value must be 0 or -1'

Type guard

def is_valid_quanto_axis(axis) -> bool:
    return axis in (0, -1)

Prevention

When it happens

Trigger: QuantoQuantizedCacheConfig(axis_value=1) with backend='quanto'; configs ported from HQQQuantizedCacheConfig where axis conventions are 0/1; asymmetric configs where the user changed axis_key but forgot axis_value or vice versa.

Common situations: Backend migration without axis translation; copy-pasted quantization configs from blog posts targeting a different backend; defaults overridden globally in a project's config factory.

Related errors


AI-assisted analysis of huggingface/transformers@a597f97485 (2026-08-14). Data as JSON: /api/errors/d0d10082aac2ac1b. Report an issue: GitHub.