{"record":{"id":"1be242c13d98044e","repo":"tracel-ai/burn","slug":"scheme-requires-a-per-tensor-scale","errorCode":null,"errorMessage":"{scheme:?} requires a per-tensor scale","messagePattern":"(.+?) requires a per-tensor scale","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-std/src/tensor/quantization.rs","lineNumber":258,"sourceCode":"            Some(_) => scales,\n        };\n        let scale_bytes = encode_scales(scales, scheme.scale_dtype());\n        bytes.extend_from_byte_slice_aligned(scale_bytes.as_slice(), QPARAM_ALIGN);\n\n        // Last, so a reader can peel it off the end before the block scales it normalizes.\n        match (global_scale_dtype(&scheme), global) {\n            (Some(dtype), Some(global)) => {\n                // Encoding the per-tensor scale narrower would round it, and the block scales were\n                // normalized against the unrounded one.\n                assert_eq!(\n                    dtype,\n                    ScaleDtype::F32,\n                    \"a two-level scheme stores its per-tensor scale as f32, got {scheme:?}\"\n                );\n                let global_bytes = encode_scales(&[global], dtype);\n                bytes.extend_from_byte_slice_aligned(global_bytes.as_slice(), QPARAM_ALIGN);\n            }\n            (Some(_), None) => panic!(\"{scheme:?} requires a per-tensor scale\"),\n            (None, Some(_)) => panic!(\"{scheme:?} does not take a per-tensor scale\"),\n            (None, None) => {}\n        }\n\n        Self {\n            bytes,\n            scheme,\n            shape,\n        }\n    }\n\n    /// The number of quantized elements.\n    pub fn num_elements(&self) -> usize {\n        self.shape.num_elements()\n    }\n\n    /// Returns the int8 quantized values with the quantization parameters.\n    pub fn into_vec_i8(self) -> (Vec<i8>, DecodedScales) {","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-std/src/tensor/quantization.rs#L240-L276","documentation":"When constructing quantization parameters (`QuantizationParameters`/qparams `new`) from raw bytes and an optional per-tensor scale, the combination of scheme and scale must be consistent. A scheme that requires a per-tensor scale (e.g. per-tensor affine symmetric schemes without block scaling) was given `Some(...)`-style bytes but no global/per-tensor scale, so construction panics. The qparams would be unusable for dequantization without that scale.","triggerScenarios":"Building quantization params for a scheme such as QAffinePerTensor / symmetric per-tensor modes while passing `None` for the per-tensor scale — e.g. `QParams::new(bytes, scheme, None)` for a scheme whose variant expects `Some(global_scale)`.","commonSituations":"Hand-writing quantized model export/serialization code and forgetting the scale; converting checkpoints between formats and dropping the scale tensor; copying param construction code from a blockwise (two-level) example and applying it to a per-tensor scheme.","solutions":["Provide the per-tensor scale (ScaleDtype::F32) when constructing params for a scheme that requires one.","Use the correct scheme variant that matches the data you actually have (e.g. a blockwise scheme if you have no global scale).","Re-quantize the tensor with burn's quantization API so scales are generated and encoded automatically instead of assembling bytes by hand."],"exampleFix":"// before\nlet params = QuantizationParameters::from_bytes(bytes, scheme, None); // panics: requires scale\n// after\nlet params = QuantizationParameters::from_bytes(bytes, scheme, Some(global_scale));","handlingStrategy":"validation","validationCode":"fn validate_qparams(scheme: QuantizationScheme, scale: Option<f32>) -> Result<(), String> {\n    match (scheme, scale) {\n        (s, None) if s.requires_per_tensor_scale() => Err(format!(\"{s:?} requires a per-tensor scale\")),\n        _ => Ok(()),\n    }\n}","typeGuard":null,"tryCatchPattern":"// panic-based constructor; validate arguments first, or wrap in catch_unwind\nlet result = std::panic::catch_unwind(|| QuantizationParameters::from_bytes(bytes, scheme, scale));","preventionTips":["Match scheme variant to the data you have before constructing qparams","Prefer burn's quantize APIs over hand-assembling scale bytes","Write unit tests that construct qparams for each scheme you ship"],"tags":["rust","panic","quantization","validation"],"backgroundTag":"missing-quantization-scale","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}