{"record":{"id":"9c98ac1c9a267e7b","repo":"huggingface/candle","slug":"block-table-must-be-u32-or-i32-got-dtype","errorCode":null,"errorMessage":"block_table must be u32 or i32, got {dtype:?}","messagePattern":"block_table must be u32 or i32, got (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"candle-flash-attn/src/lib.rs","lineNumber":750,"sourceCode":"            let (seqlens_q_ptr, _guard) = seqlens_q.device_ptr(&stream);\n            let (seqlens_k_ptr, _guard) = seqlens_k.device_ptr(&stream);\n            let (block_table_ptr, block_table_batch_stride) =\n                if let Some((block_table, offset, stride)) = block_table.as_ref() {\n                    match (&**block_table, self.block_table.as_ref().unwrap().dtype()) {\n                        (candle::Storage::Cuda(block_table), DType::U32) => {\n                            let block_table = block_table.as_cuda_slice::<u32>()?;\n                            let block_table = block_table.slice(*offset..);\n                            let (ptr, _guard) = block_table.device_ptr(&stream);\n                            (ptr as *const i32, *stride as u32)\n                        }\n                        (candle::Storage::Cuda(block_table), DType::I32) => {\n                            let block_table = block_table.as_cuda_slice::<i32>()?;\n                            let block_table = block_table.slice(*offset..);\n                            let (ptr, _guard) = block_table.device_ptr(&stream);\n                            (ptr as *const i32, *stride as u32)\n                        }\n                        (_, dtype) => {\n                            candle::bail!(\"block_table must be u32 or i32, got {dtype:?}\")\n                        }\n                    }\n                } else {\n                    (std::ptr::null(), 0)\n                };\n            let (mm_prefix_ranges_ptr, mm_prefix_range_batch_stride, max_mm_prefix_ranges) =\n                if let Some((storage, offset, stride, max_ranges)) = mm_prefix_ranges.as_ref() {\n                    match &**storage {\n                        candle::Storage::Cuda(mm_prefix_ranges) => {\n                            let mm_prefix_ranges = mm_prefix_ranges.as_cuda_slice::<i32>()?;\n                            let mm_prefix_ranges = mm_prefix_ranges.slice(*offset..);\n                            let (ptr, _guard) = mm_prefix_ranges.device_ptr(&stream);\n                            (ptr as *const i32, *stride as u32, *max_ranges as i32)\n                        }\n                        _ => unreachable!(\"mm_prefix_ranges must be a cuda tensor\"),\n                    }\n                } else {\n                    (std::ptr::null(), 0, 0)","sourceCodeStart":732,"sourceCodeEnd":768,"githubUrl":"https://github.com/huggingface/candle/blob/d5fee525bfde3273eb7c9b75fd2bc4937be867ca/candle-flash-attn/src/lib.rs#L732-L768","documentation":"In the paged-attention/varlen path, block_table entries are read as 32-bit integers via raw pointers; only u32 and i32 storages are accepted. Any other dtype for the block table is rejected with this error.","triggerScenarios":"Passing a block_table tensor of dtype f32, i64, u16, etc. to flash-attn with a block table (e.g. page table built as i64 like PyTorch defaults).","commonSituations":"Porting paged-attention code from PyTorch where page tables are int64; building block tables with candle's default i64 from_from_vec of i64 values.","solutions":["Convert the block table with .to_dtype(DType::I32)? (or U32) before the call","Build the table as i32 from the start (from_vec of i32 values)","Check the dtype at construction with a debug_assert"],"exampleFix":"// before\nlet block_table = Tensor::from_vec(pages_i64, (b, max_blocks), &dev)?; // i64\n// after\nlet block_table = Tensor::from_vec(pages_i32, (b, max_blocks), &dev)?; // i32","handlingStrategy":"validation","validationCode":"if !matches!(block_table.dtype(), candle::DType::I32 | candle::DType::U32) {\n    let block_table = block_table.to_dtype(candle::DType::I32)?;\n}","typeGuard":"fn is_i32_or_u32(t: &Tensor) -> bool {\n    matches!(t.dtype(), candle::DType::I32 | candle::DType::U32)\n}","tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"block_table must be u32 or i32\") => {\n        let bt = block_table.to_dtype(candle::DType::I32)?;\n        // retry\n    }\n    other => other?,\n}","preventionTips":["Build block tables as i32 explicitly (PyTorch defaults to i64)","Convert at the boundary when porting from other frameworks","Add a dtype assert where the table is constructed"],"tags":["cuda","flash-attn","dtype","paged-attention","i32"],"backgroundTag":"dtype-mismatch","analyzedSha":"d5fee525bfde3273eb7c9b75fd2bc4937be867ca","analyzedAt":"2026-09-02T00:15:47.023Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}