{"record":{"id":"41325e986350d076","repo":"huggingface/transformers","slug":"you-called-get-mask-sizes-on-layer-index-layer","errorCode":null,"errorMessage":"You called `get_mask_sizes` on layer index {layer_idx}, but this layer is a LinearAttention layer, which does not track sequence length.","messagePattern":"You called `get_mask_sizes` on layer index (.+?), but this layer is a LinearAttention layer, which does not track sequence length\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/transformers/cache_utils.py","lineNumber":1570,"sourceCode":"            return all(self.layers[layer_idx].has_previous_state.values())\n        return self.layers[layer_idx].has_previous_state[state_idx]\n\n    def get_mask_sizes(self, query_length: int, layer_idx: int) -> tuple[int, int]:\n        \"\"\"\n        Return a tuple (kv_length, kv_offset) corresponding to the length and offset that will be returned for\n        the given layer at `layer_idx`.\n        The masks are then prepared according to the given lengths (kv_length, kv_offset) and patterns for each layer.\n        \"\"\"\n        # For DynamicCache, where the layers are created at runtime -> if it was not yet created, the size is\n        # simply the query_length\n        if layer_idx >= len(self.layers):\n            return query_length, 0\n\n        # For alternating attention/linear attention caches, `get_mask_sizes` needs to use attention layer idx when called with default layer_idx\n        if not isinstance(self.layers[layer_idx], CacheLayerMixin):\n            # If this is called with non-default arg, raise\n            if layer_idx != 0:\n                raise ValueError(\n                    f\"You called `get_mask_sizes` on layer index {layer_idx}, but this layer is a LinearAttention layer, which \"\n                    \"does not track sequence length.\"\n                )\n            try:\n                # Use the first attention layer\n                layer_idx = next(idx for idx in range(len(self)) if isinstance(self.layers[idx], CacheLayerMixin))\n            except StopIteration:\n                raise ValueError(\n                    \"`get_mask_sizes` can only be called on Attention layers, and the current Cache seem to only contain \"\n                    \"LinearAttention layers.\"\n                )\n\n        return self.layers[layer_idx].get_mask_sizes(query_length)\n\n    def get_query_offset(self, layer_idx: int = 0) -> int:\n        \"\"\"Returns the current offset of the query for the given `layer_idx`. It's always equal to the cache length, i.e.\n        `get_seq_length(layer_idx)`, except for MTP layers.\n        \"\"\"","sourceCodeStart":1552,"sourceCodeEnd":1588,"githubUrl":"https://github.com/huggingface/transformers/blob/a597f974857b3d92939971296bc0deb93d33d780/src/transformers/cache_utils.py#L1552-L1588","documentation":"Cache.get_mask_sizes() raises ValueError when called with an explicit non-zero layer_idx pointing at a LinearAttention layer. Mask sizes depend on KV sequence length, which linear attention layers do not track; only the default path (layer_idx=0, re-dispatched to the first attention layer) is valid.","triggerScenarios":"cache.get_mask_sizes(query_length, layer_idx=k) with k != 0 where layers[k] is linear attention — typically inside per-layer mask preparation for hybrid models.","commonSituations":"Custom attention-mask preparation loops over all layers; alternating attention/linear attention architectures where most indices are linear attention.","solutions":["Call with layer_idx=0 / default to auto-select the first attention layer, or pass an attention layer index","Skip linear attention indices: isinstance check on cache.layers[idx]","Rely on the model's built-in mask preparation, which dispatches correctly"],"exampleFix":"# before\nfor i in range(len(cache.layers)):\n    kv_len, off = cache.get_mask_sizes(q_len, layer_idx=i)\n\n# after\nfor i in range(len(cache.layers)):\n    if isinstance(cache.layers[i], CacheLayerMixin):\n        kv_len, off = cache.get_mask_sizes(q_len, layer_idx=i)","handlingStrategy":"type-guard","validationCode":"from transformers.cache_utils import CacheLayerMixin\n\nif layer_idx == 0 or isinstance(cache.layers[layer_idx], CacheLayerMixin):\n    kv_len, offset = cache.get_mask_sizes(query_length, layer_idx=layer_idx)","typeGuard":"from transformers.cache_utils import CacheLayerMixin\n\ndef tracks_mask_sizes(layer) -> bool:\n    return isinstance(layer, CacheLayerMixin)","tryCatchPattern":null,"preventionTips":["Defer mask preparation to the modeling code, which already dispatches per layer type","Use the default layer_idx on hybrid caches; only pass explicit indices for attention layers"],"tags":["cache","linear-attention","mask","layer-type","valueerror"],"backgroundTag":null,"analyzedSha":"a597f974857b3d92939971296bc0deb93d33d780","analyzedAt":"2026-08-14T18:24:08.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}