{"record":{"id":"5ea882e856587cc3","repo":"xai-org/x-algorithm","slug":"block-sparse-arrays-cover-bs-num-blocks-m-tiles-5ea882","errorCode":null,"errorMessage":"block-sparse arrays cover {bs_num_blocks} m-tiles but the kernel will iterate {_expected_m_blocks} (packed_S={packed_S}). Pass packed_seq_len (the physical packed row length) to build_block_sparse_layout so every physical tile has an entry.","messagePattern":"block-sparse arrays cover (.+?) m-tiles but the kernel will iterate (.+?) \\(packed_S=(.+?)\\)\\. Pass packed_seq_len \\(the physical packed row length\\) to build_block_sparse_layout so every physical tile has an entry\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"phoenix/xrex/cutedsl/ranker_attention_varlen_fa4.py","lineNumber":337,"sourceCode":"    sr_q = ((packed_S + block_size - 1) // block_size) * block_size\n    sr_k = sr_q\n    dKV_postprocess = True\n    use_pack_gqa = qpk > 1 and (block_size % qpk == 0)\n\n    fwd_bs, _ = block_sparse_layout\n    if valid_block_upper is None or valid_block_lower is None:\n        if valid_block_upper is not None or valid_block_lower is not None:\n            raise ValueError(\"valid_block_upper and valid_block_lower must be provided together\")\n        valid_block_upper = jnp.zeros(fwd_bs[2].shape, dtype=jnp.int32)\n        valid_block_lower = jnp.zeros(fwd_bs[2].shape, dtype=jnp.int32)\n    valid_block_upper = jnp.broadcast_to(valid_block_upper, fwd_bs[2].shape)\n    valid_block_lower = jnp.broadcast_to(valid_block_lower, fwd_bs[2].shape)\n    bs_max_hist_blocks = int(fwd_bs[3].shape[-1])\n    bs_num_blocks = int(fwd_bs[3].shape[-2])\n\n    _expected_m_blocks = (packed_S + block_size - 1) // block_size\n    if bs_num_blocks != _expected_m_blocks:\n        raise ValueError(\n            f\"block-sparse arrays cover {bs_num_blocks} m-tiles but the kernel \"\n            f\"will iterate {_expected_m_blocks} (packed_S={packed_S}). \"\n            \"Pass packed_seq_len (the physical packed row length) to \"\n            \"build_block_sparse_layout so every physical tile has an entry.\"\n        )\n\n    cache_key = (\n        \"packed\",\n        head_dim,\n        num_q_heads,\n        num_kv_heads,\n        batch_size,\n        packed_S,\n        bs_num_blocks,\n        bs_max_hist_blocks,\n        use_pack_gqa,\n    )\n","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/phoenix/xrex/cutedsl/ranker_attention_varlen_fa4.py#L319-L355","documentation":"The varlen FA4 kernel iterates ceil(packed_S / block_size) physical m-tiles over the packed sequence rows, and every physical tile must have an entry in the block-sparse layout's index array (bs_num_blocks from fwd_bs[3]). If the layout was built from logical per-sequence lengths instead of the physical packed row length, some tiles would have no sparsity entry and the kernel would fault or misbehave, so it raises with guidance to pass packed_seq_len to build_block_sparse_layout.","triggerScenarios":"Calling ranker_attention_varlen_fa4 via sharded_mha where build_block_sparse_layout received total/max logical seq_len (sum of cu_seqlens minus padding, or max len) instead of packed_S = physical number of packed rows.","commonSituations":"Migrating from the non-varlen FA4 path where seq_len was the right argument; padding the packed buffer to a multiple and passing the padded logical length; computing packed_S from batch size x max_len instead of the actual packed row count.","solutions":["Pass packed_seq_len (the physical packed row length, matching packed_S given to the kernel) to build_block_sparse_layout","Ensure packed_S and the layout are derived from the same cu_seqlens/packing buffer","Add an assertion in your pipeline: build_block_sparse_layout(packed_seq_len=packed_S, ...) right where packed_S is computed so they cannot drift"],"exampleFix":"# before\nlayout = build_block_sparse_layout(seq_len=max_len, ...)\nout = ranker_attention_varlen_fa4(..., packed_S=packed_S, block_size=bs, block_sparse_layout=layout)\n# after\nlayout = build_block_sparse_layout(packed_seq_len=packed_S, ...)\nout = ranker_attention_varlen_fa4(..., packed_S=packed_S, block_size=bs, block_sparse_layout=layout)","handlingStrategy":"validation","validationCode":"expected_m_blocks = (packed_S + block_size - 1) // block_size\nassert int(fwd_bs[3].shape[-2]) == expected_m_blocks, \\\n    \"layout built without packed_seq_len; rebuild with packed_seq_len=packed_S\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compute packed_S once and thread it to both build_block_sparse_layout and the kernel","Add a helper that builds layout + calls the kernel so lengths cannot diverge","Property-test packing with ragged batch sizes"],"tags":["cuda","cutedsl","varlen-attention","block-sparse","packing"],"backgroundTag":"layout-shape-mismatch","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}