{"record":{"id":"5045026be1c66378","repo":"tracel-ai/burn","slug":"requires-autodiff-tensor","errorCode":null,"errorMessage":"Requires autodiff tensor.","messagePattern":"Requires autodiff tensor\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-dispatch/src/backend.rs","lineNumber":351,"sourceCode":"                #[cfg(cube_backend)]\n                DispatchTensorKind::Cube(tensor) => tensor.autodiff().backward(),\n                #[cfg(any(feature = \"flex\", default_backend))]\n                DispatchTensorKind::Flex(tensor) => tensor.autodiff().backward(),\n                #[cfg(feature = \"ndarray\")]\n                DispatchTensorKind::NdArray(tensor) => tensor.autodiff().backward(),\n                #[cfg(feature = \"tch\")]\n                DispatchTensorKind::LibTorch(tensor) => tensor.autodiff().backward(),\n                #[cfg(feature = \"remote\")]\n                DispatchTensorKind::Remote(tensor) => tensor.autodiff().backward(),\n                #[cfg(feature = \"capture\")]\n                DispatchTensorKind::Capture(_) => {\n                    panic!(\"Capture tensors do not support autodiff\")\n                }\n                DispatchTensorKind::Autodiff(_) => {\n                    panic!(\"Autodiff should not wrap an autodiff tensor.\")\n                }\n            },\n            _ => panic!(\"Requires autodiff tensor.\"),\n        }\n    }\n\n    fn grad(tensor: &DispatchTensor, grads: &Self::Gradients) -> Option<DispatchTensor> {\n        let DispatchTensor { kind, .. } = tensor;\n        let grad: Option<DispatchTensorKind> = match &kind {\n            DispatchTensorKind::Autodiff(inner_kind) => match &**inner_kind {\n                #[cfg(cube_backend)]\n                DispatchTensorKind::Cube(tensor) => tensor\n                    .as_autodiff()\n                    .grad(grads)\n                    .map(|t| DispatchTensorKind::Cube(crate::BackendTensor::Float(t))),\n                #[cfg(any(feature = \"flex\", default_backend))]\n                DispatchTensorKind::Flex(tensor) => tensor\n                    .as_autodiff()\n                    .grad(grads)\n                    .map(|t| DispatchTensorKind::Flex(crate::BackendTensor::Float(t))),\n                #[cfg(feature = \"ndarray\")]","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-dispatch/src/backend.rs#L333-L369","documentation":"backward() only handles tensors whose outer kind is DispatchTensorKind::Autodiff. Any other kind (NdArray, LibTorch, Cube, Flex, Remote, Capture) reaching backward() directly panics with 'Requires autodiff tensor.' — the tensor was never wrapped for gradient tracking.","triggerScenarios":"Calling Dispatch::backward(tensor) where tensor.kind is not Autodiff — e.g. a plain inference tensor from backend.eval()/forward, or a grad() output (which returns inner-backend tensors with autodiff: Disabled) fed back into backward().","commonSituations":"Calling backward() on outputs of no_grad/eval inference; using a tensor returned by grad() or inner() as a new loss root; forgetting to enable the 'autodiff' feature so tensors are never autodiff-wrapped.","solutions":["Ensure the tensor comes from an autodiff-tracked computation (training forward pass), not an eval/inference call","Enable the 'autodiff' feature and use Autodiff-wrapped tensors for training","Do not reuse grad()/inner() results as backward() roots; recompute the loss with the autodiff backend"],"exampleFix":"// before\nlet out = model.eval(x);\nlet grads = out.backward(); // panics: not an autodiff tensor\n// after\nlet out = model.forward(x); // autodiff-tracked\nlet grads = out.backward();","handlingStrategy":"type-guard","validationCode":"fn ensure_autodiff(t: &DispatchTensor) -> Result<(), String> {\n    match &t.kind {\n        DispatchTensorKind::Autodiff(_) => Ok(()),\n        _ => Err(\"backward() requires an autodiff-wrapped tensor\".into()),\n    }\n}","typeGuard":"fn is_autodiff_tensor(t: &DispatchTensor) -> bool {\n    matches!(t.kind, DispatchTensorKind::Autodiff(_))\n}","tryCatchPattern":"let result = std::panic::catch_unwind(AssertUnwindSafe(|| Dispatch::backward(loss)));\nmatch result {\n    Ok(grads) => grads,\n    Err(_) => panic!(\"loss tensor was not autodiff-tracked; recompute with training forward\"),\n}","preventionTips":["Call backward() only on tensors from a training (autodiff) forward pass","Do not reuse grad()/inner()/eval outputs as backward roots","Enable the 'autodiff' feature when training"],"tags":["rust","autodiff","panic","tensor"],"backgroundTag":"requires-autodiff-tensor","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"}