{"record":{"id":"0b03090f5d7b908e","repo":"tracel-ai/burn","slug":"an-enabled-float-tensor-must-use-an-autodiff-primi-0b0309","errorCode":null,"errorMessage":"an enabled float tensor must use an autodiff primitive","messagePattern":"an enabled float tensor must use an autodiff primitive","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-dispatch/src/tensor.rs","lineNumber":398,"sourceCode":"\n    fn device(&self) -> Self::Device {\n        #[allow(unused_mut)]\n        let mut device = self.kind.device();\n\n        #[cfg(feature = \"autodiff\")]\n        match (&self.kind, self.autodiff) {\n            (DispatchTensorKind::Autodiff(_), DispatchAutodiffContext::Disabled) => {\n                panic!(\"an autodiff float primitive must have an enabled autodiff context\")\n            }\n            (DispatchTensorKind::Autodiff(_), DispatchAutodiffContext::Enabled(strategy)) => {\n                let DispatchDevice::Autodiff(device) = &mut device else {\n                    unreachable!(\"autodiff primitive must report an autodiff device\")\n                };\n                device.checkpointing = strategy;\n            }\n            (_, DispatchAutodiffContext::Enabled(strategy)) => {\n                if self.dtype().is_float() {\n                    panic!(\"an enabled float tensor must use an autodiff primitive\")\n                }\n                device = DispatchDevice::autodiff(device);\n                let DispatchDevice::Autodiff(device) = &mut device else {\n                    unreachable!()\n                };\n                device.checkpointing = strategy;\n            }\n            (_, DispatchAutodiffContext::Disabled) => {}\n        }\n\n        device\n    }\n}\n\nimpl DispatchTensorKind {\n    /// Returns the backend tensor kind name.\n    pub(crate) fn name(&self) -> &'static str {\n        match self {","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-dispatch/src/tensor.rs#L380-L416","documentation":"When a tensor's autodiff context is Enabled but the tensor itself is a plain float primitive (not an `Autodiff` kind), `device()` panics: gradients cannot be tracked on a non-autodiff float primitive. The invariant is that an enabled float tensor must wrap an autodiff primitive; non-float tensors are permitted since they are just re-wrapped.","triggerScenarios":"Calling `device()` (e.g. via `assert_enabled_float`) on a tensor with `DispatchAutodiffContext::Enabled(_)` whose kind is a plain Float dispatch kind rather than `DispatchTensorKind::Autodiff`.","commonSituations":"Mixing tensors created inside and outside an autodiff session, custom backends wrapping raw float primitives while marking the context as autodiff-enabled, or partial migration from inference to training code paths.","solutions":["Wrap the float primitive in the autodiff primitive (`DispatchTensorKind::Autodiff`) when the context is enabled.","Create the tensor via the autodiff-aware constructor so kind and context stay consistent.","Disable the autodiff context for tensors that are intentionally non-autodiff."],"exampleFix":"// before\nDispatchTensor { kind: DispatchTensorKind::Float(p), autodiff: DispatchAutodiffContext::Enabled(strategy) }\n// after\nDispatchTensor { kind: DispatchTensorKind::Autodiff(autodiff_from(p)), autodiff: DispatchAutodiffContext::Enabled(strategy) }","handlingStrategy":"validation","validationCode":"if matches!(tensor.autodiff, DispatchAutodiffContext::Enabled(_)) {\n    assert!(matches!(tensor.kind, DispatchTensorKind::Autodiff(_)), \"enabled float tensor must be autodiff primitive\");\n}","typeGuard":"fn enabled_float_is_autodiff(t: &DispatchTensor) -> bool {\n    !matches!(t.autodiff, DispatchAutodiffContext::Enabled(_))\n        || matches!(t.kind, DispatchTensorKind::Autodiff(_))\n}","tryCatchPattern":"let result = std::panic::catch_unwind(AssertUnwindSafe(|| tensor.device()));\nmatch result {\n    Ok(d) => use_device(d),\n    Err(_) => eprintln!(\"enabled context on non-autodiff float primitive\"),\n}","preventionTips":["Wrap float primitives in the autodiff primitive whenever the autodiff context is enabled.","Create training tensors only via autodiff-aware APIs, never by hand-assembling DispatchTensor.","Keep inference (Disabled) and training (Enabled) tensor creation in separate, typed code paths."],"tags":["rust","tensor","autodiff","invariant-violation","panic"],"backgroundTag":"autodiff-context-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"}