{"record":{"id":"571a9813e21a56c8","repo":"huggingface/transformers","slug":"you-called-get-seq-length-on-layer-index-layer","errorCode":null,"errorMessage":"You called `get_seq_length` on layer index {layer_idx}, but this layer is a LinearAttention layer, which does not track sequence length.","messagePattern":"You called `get_seq_length` 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":1494,"sourceCode":"            if not layer.supports_early_init or layer.is_initialized:\n                continue\n            # Note that the initialization needs all dimensions (except -2), as well as device and dtype, so we use\n            # this fake tensor approach. It has size 0 on the -2 dimension, so it does not allocate any data (it only\n            # creates an empty tensor with correct shape, dtype and device), which is very efficient and practical\n            fake_kv_tensor = torch.zeros((batch_size, layer_num_heads, 0, layer_head_dim), dtype=dtype, device=device)\n            # Init the layer\n            layer.lazy_initialization(fake_kv_tensor, fake_kv_tensor)\n\n    def get_seq_length(self, layer_idx: int = 0) -> int:\n        \"\"\"Returns the sequence length of the cache for the given layer.\"\"\"\n        if layer_idx >= len(self.layers):\n            return 0\n\n        # For alternating attention/linear attention  caches, `get_seq_length` 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_seq_length` 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_seq_length` 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_seq_length()\n\n    def get_max_length(self, layer_idx: int | None = None) -> int:\n        \"\"\"\n        Returns the maximum length of the cache. If `layer_idx` is not provided (default), this returns the maximum\n        across all layers. Otherwise, return the maximum supported value for the given layer.","sourceCodeStart":1476,"sourceCodeEnd":1512,"githubUrl":"https://github.com/huggingface/transformers/blob/a597f974857b3d92939971296bc0deb93d33d780/src/transformers/cache_utils.py#L1476-L1512","documentation":"Cache.get_seq_length() raises ValueError when called with an explicit non-zero layer_idx pointing at a LinearAttention layer. Linear attention layers have no sequence-length dimension (fixed-size states), so only the automatic default path (layer_idx=0, which re-dispatches to the first attention layer) is allowed.","triggerScenarios":"cache.get_seq_length(layer_idx=k) with k != 0 where layers[k] is a linear attention layer — e.g. looping over all layer indices to collect per-layer lengths on a hybrid cache.","commonSituations":"Per-layer diagnostics or logging loops copied from pure-attention models; code that assumes every layer tracks KV length; alternating attention/linear attention models (e.g. Qwen3-Next, Falcon-H1) where many indices are linear attention.","solutions":["Only query attention layer indices, or call get_seq_length() with the default layer_idx to auto-select the first attention layer","Filter indices by isinstance(layer, CacheLayerMixin) before querying","For hybrid caches, use config.layer_types to know which indices are safe"],"exampleFix":"# before\nlengths = [cache.get_seq_length(i) for i in range(len(cache.layers))]\n\n# after\nlengths = [\n    cache.get_seq_length(i)\n    for i in range(len(cache.layers))\n    if isinstance(cache.layers[i], CacheLayerMixin)\n]","handlingStrategy":"type-guard","validationCode":"from transformers.cache_utils import CacheLayerMixin\n\nif layer_idx != 0:\n    assert isinstance(cache.layers[layer_idx], CacheLayerMixin), \"not an attention layer\"\nlength = cache.get_seq_length(layer_idx)","typeGuard":"from transformers.cache_utils import CacheLayerMixin\n\ndef tracks_seq_length(layer) -> bool:\n    return isinstance(layer, CacheLayerMixin)","tryCatchPattern":null,"preventionTips":["Call get_seq_length() with no argument on hybrid caches; the default auto-selects the first attention layer","Never loop over all layer indices assuming uniform cache semantics on hybrid models"],"tags":["cache","linear-attention","layer-type","get-seq-length","valueerror"],"backgroundTag":null,"analyzedSha":"a597f974857b3d92939971296bc0deb93d33d780","analyzedAt":"2026-08-14T18:24:08.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}