{"record":{"id":"68e37e3d4256ebee","repo":"tracel-ai/burn","slug":"expected-autodiff-wrapped-float-tensor-for-backend","errorCode":null,"errorMessage":"Expected autodiff-wrapped float tensor for backend {backend}.","messagePattern":"Expected autodiff-wrapped float tensor for backend (.+?)\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-dispatch/src/macros.rs","lineNumber":415,"sourceCode":"                    \"Tensor is on the wrong backend (expected {}).\",\n                    stringify!($Backend)\n                ),\n            })\n            .collect::<Vec<_>>()\n    };\n\n    // Autodiff-wrapped backend\n    (@autodiff $Backend:ident, $vec:expr, $kind:ident) => {\n        $vec.into_iter()\n            .map(|t| match t.kind {\n                $crate::DispatchTensorKind::Autodiff(inner) => match *inner {\n                    $crate::DispatchTensorKind::$Backend(inner) => inner.$kind(),\n                    _ => panic!(\n                        \"Autodiff float tensor is on the wrong backend (expected {}).\",\n                        stringify!($Backend)\n                    ),\n                },\n                _ => panic!(\n                    \"Expected autodiff-wrapped float tensor for backend {}.\",\n                    stringify!($Backend)\n                ),\n            })\n            .collect::<Vec<_>>()\n    };\n}\n\n/// Match arm generator for `transaction_op`.\nmacro_rules! transaction_op_arms {\n    ($tx:ident, $first:expr; $([$Backend:ident, $cfg:meta]),*) => {{\n        match &$first.kind {\n            // Autodiff arm first\n            #[cfg(feature = \"autodiff\")]\n            $crate::DispatchTensorKind::Autodiff(inner) => {\n                // Recursively dispatch on inner\n                match **inner {\n                    $(","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-dispatch/src/macros.rs#L397-L433","documentation":"In the `@autodiff` unwrap arm, if the tensor's kind is not `DispatchTensorKind::Autodiff` at all (it is a plain backend tensor or another kind), the macro panics asking for an autodiff-wrapped float tensor. The operation requires gradients, so a primitive tensor is insufficient.","triggerScenarios":"Calling an autodiff-dispatched float operation with a raw backend tensor (not `AutodiffTensor`), or a non-float tensor where a float autodiff tensor is required.","commonSituations":"Mixing inference-time primitive tensors into a training graph; calling `.detach()`/`inner()` on a tensor and reusing the result where the autodiff tensor is expected.","solutions":["Pass an `AutodiffTensor` (created via `AutodiffTensor::from` / backend tensor `.autodiff()`), not the primitive tensor","Ensure the operation is invoked through the Autodiff backend, not the base backend directly","Check the tensor is a float tensor as required by the op"],"exampleFix":"// before\nop(primitive_tensor);\n// after\nop(AutodiffTensor::from(primitive_tensor));","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn as_autodiff<B: AutodiffBackend>(t: &Tensor<B, D>) -> &Tensor<B, D> { t } // Rust's type system: pass Tensor<Autodiff<B>, D> not Tensor<B, D>; the compiler rejects primitives","tryCatchPattern":null,"preventionTips":["Keep the Autodiff-wrapped backend type parameter through the whole training graph","Don't call `.detach()`/`.inner()` until you intend to leave the graph","Use distinct type aliases for train (autodiff) vs inference tensors"],"tags":["rust","autodiff","tensor-kind","panic","burn"],"backgroundTag":"tensor-backend-mismatch","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"}