{"record":{"id":"71a6de7e2c298603","repo":"tracel-ai/burn","slug":"a-per-tensor-scale-should-come-with-a-two-level-sc","errorCode":null,"errorMessage":"a per-tensor scale should come with a two-level scheme","messagePattern":"a per-tensor scale should come with a two-level scheme","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-ndarray/src/ops/qtensor.rs","lineNumber":98,"sourceCode":"    }\n\n    fn quantize(\n        tensor: FloatTensor<Self>,\n        scheme: &QuantScheme,\n        qparams: QuantizationParametersPrimitive<Self>,\n    ) -> QuantizedTensor<Self> {\n        let shape = tensor.shape();\n        let data_f = tensor.into_data();\n        let scales = qparams.scales.into_data().convert::<f32>();\n        // Quantize against the scale that will actually be stored, so a save/load round trip\n        // reproduces these values instead of drifting by the scale dtype's rounding error.\n        let scales: Vec<f32> = scales\n            .iter::<f32>()\n            .map(|s| scale_to_dtype(s, scheme.scale_dtype()))\n            .collect();\n        let global = qparams.global.map(|global| {\n            let dtype = global_scale_dtype(scheme)\n                .expect(\"a per-tensor scale should come with a two-level scheme\");\n            let global = global.into_data().convert::<f32>();\n            scale_to_dtype(global.iter::<f32>().next().unwrap(), dtype)\n        });\n\n        // Implement with ndarray instead of QuantizationStrategy?\n        let (data, qparams) = match (scheme.block_size(), scheme) {\n            (\n                None,\n                QuantScheme {\n                    mode: QuantMode::Symmetric,\n                    // `Q2S` is supported natively (stored as i8): it feeds the multiply-free\n                    // ternary matmul fast path in `q_matmul` (BitNet b1.58).\n                    #[cfg(not(feature = \"export_tests\"))]\n                        value: QuantValue::Q8F | QuantValue::Q8S | QuantValue::Q2S,\n                    // For tests, \"native\" sub-byte quant serves as a reference for value equality.\n                    // Values are stored as i8 regardless.\n                    #[cfg(feature = \"export_tests\")]\n                        value:","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-ndarray/src/ops/qtensor.rs#L80-L116","documentation":"Invariant check in the ndarray backend's `quantize`: a per-tensor scale was supplied, but the quantization scheme is not a two-level scheme (there is no global scale slot for it), so the qparams are inconsistent with the scheme and quantization panics.","triggerScenarios":"Thrown at crates/burn-ndarray/src/ops/qtensor.rs:98 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Provide only the scales the scheme expects (single scale for one-level schemes)","Use a two-level scheme when a global per-tensor scale is needed","Verify how QuantizationParametersPrimitive was constructed"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}