{"record":{"id":"4bc0695e1dd11113","repo":"tracel-ai/burn","slug":"unexpected-autodiff-variant-provided-to-from-back","errorCode":null,"errorMessage":"Unexpected Autodiff variant provided to `from_backend`","messagePattern":"Unexpected Autodiff variant provided to `from_backend`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-dispatch/src/tensor.rs","lineNumber":568,"sourceCode":"                let kind = match tensor {\n                    // Inverse: Wrap the `Float` variant back into the backend's `Autodiff` primitive variant\n                    BackendTensor::Float(t) => {\n                        let ad_tensor = BackendTensor::Autodiff(t);\n                        // Wrap in the concrete backend's dispatch container\n                        let inner_dispatch = DispatchTensorKind::$backend(ad_tensor);\n                        // Re-apply the outer Autodiff dispatch wrapper\n                        DispatchTensorKind::Autodiff(Box::new(inner_dispatch))\n                    }\n\n                    // Pass-throughs for non-differentiable types\n                    BackendTensor::Int(t) => DispatchTensorKind::$backend(BackendTensor::Int(t)),\n                    BackendTensor::Bool(t) => DispatchTensorKind::$backend(BackendTensor::Bool(t)),\n                    BackendTensor::Quantized(t) => {\n                        DispatchTensorKind::$backend(BackendTensor::Quantized(t))\n                    }\n\n                    BackendTensor::Autodiff(_) => {\n                        panic!(\"Unexpected Autodiff variant provided to `from_backend`\",)\n                    }\n                };\n\n                DispatchTensor {\n                    kind,\n                    autodiff: DispatchAutodiffContext::Enabled(C::STRATEGY),\n                }\n            }\n        }\n    };\n}\n\n// One invocation per dispatch variant. Every cubecl runtime is the same `Cube`\n// backend, so they share the one impl rather than getting seven identical ones.\nimpl_dispatch_conversion!(Cube, cube_backend);\nimpl_dispatch_conversion!(Flex, any(feature = \"flex\", default_backend));\nimpl_dispatch_conversion!(Remote, feature = \"remote\");\nimpl_dispatch_conversion!(Capture, feature = \"capture\");","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-dispatch/src/tensor.rs#L550-L586","documentation":"The `from_backend` macro-generated constructor re-tags each `BackendTensor` variant into a backend-specific `DispatchTensorKind`. The `Autodiff` variant has no valid target in this conversion, so encountering one is an internal misuse and the code panics with 'Unexpected Autodiff variant provided to `from_backend`'.","triggerScenarios":"Passing a `BackendTensor::Autodiff(_)` into the `from_backend` constructor for a concrete (non-autodiff) backend context — i.e. feeding an autodiff-wrapped tensor into a path that expects plain backend primitives.","commonSituations":"Custom backend or dispatch glue that forwards tensors without stripping the autodiff wrapper, or calling a non-autodiff constructor from autodiff-enabled code.","solutions":["Strip the autodiff wrapper (extract the inner backend tensor) before calling `from_backend`.","Use the autodiff-specific constructor/path that accepts `BackendTensor::Autodiff`.","Add an upstream variant check and route autodiff tensors to the correct conversion."],"exampleFix":"// before\nlet dt = DispatchTensor::from_backend(backend_tensor); // Autodiff variant panics\n// after\nlet dt = match backend_tensor {\n    BackendTensor::Autodiff(t) => DispatchTensor::from_backend(BackendTensor::Float(t.inner())),\n    other => DispatchTensor::from_backend(other),\n};","handlingStrategy":"validation","validationCode":"if matches!(backend_tensor, BackendTensor::Autodiff(_)) { /* strip wrapper or use autodiff path */ }","typeGuard":"fn is_plain_backend_tensor<B: Backend>(t: &BackendTensor<B>) -> bool {\n    !matches!(t, BackendTensor::Autodiff(_))\n}","tryCatchPattern":"let result = std::panic::catch_unwind(AssertUnwindSafe(|| DispatchTensor::from_backend(bt.clone())));\nmatch result {\n    Ok(dt) => use_tensor(dt),\n    Err(_) => eprintln!(\"autodiff variant passed to non-autodiff constructor\"),\n}","preventionTips":["Strip the Autodiff wrapper before calling macro-generated from_backend constructors.","Route autodiff tensors through autodiff-specific construction paths.","Centralize BackendTensor -> DispatchTensor conversion in one checked helper."],"tags":["rust","tensor","autodiff","invalid-argument","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"}