{"record":{"id":"88aeb885ca190516","repo":"tracel-ai/burn","slug":"autodiff-should-not-wrap-an-autodiff-device-88aeb8","errorCode":null,"errorMessage":"Autodiff should not wrap an autodiff device.","messagePattern":"Autodiff should not wrap an autodiff device\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-dispatch/src/ops/distributed.rs","lineNumber":97,"sourceCode":"                $crate::DispatchDevice::$Backend(_) => {\n                    type B = $crate::backends::Autodiff<$crate::backends::$Backend>;\n                    let $inner_devices = $devices\n                        .iter()\n                        .map(|d| {\n                            // In a build with only one dispatch variant compiled in, the\n                            // pattern is irrefutable and the else clause is dead — which is\n                            // the point: it only guards the multi-backend builds.\n                            #[allow(irrefutable_let_patterns)]\n                            let DispatchDevice::$Backend(dev) = d else {\n                                unreachable!(\"All devices are expected to be of the same variant.\")\n                            };\n                            dev.clone()\n                        })\n                        .collect::<Vec<_>>();\n                    $body\n                }\n            )*\n            $crate::DispatchDevice::Autodiff(_) => panic!(\"Autodiff should not wrap an autodiff device.\"),\n            #[allow(unreachable_patterns)]\n            other => panic!(\"Distributed operations are not supported for device {other:?}\"),\n        }\n    };\n}\n\n/// Dispatches an operation body based on the provided devices.\nmacro_rules! dispatch_distributed_devices {\n    ($device:expr, $devices:expr, |$inner_devices:ident| $body:expr) => {\n        distributed_backend_list!(\n            dispatch_distributed_devices_arms,\n            $device,\n            $devices,\n            |$inner_devices| $body\n        )\n    };\n}\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-dispatch/src/ops/distributed.rs#L79-L115","documentation":"The distributed device dispatch macro explicitly rejects `DispatchDevice::Autodiff`: autodiff is a wrapper around a backend, not a physical device, so nesting it is always a programming error and the library panics with 'Autodiff should not wrap an autodiff device'.","triggerScenarios":"Constructing or passing a DispatchDevice::Autodiff that itself contains another Autodiff device — e.g. wrapping an already-autodiff-wrapped device when setting up a distributed operation or distributed parameters.","commonSituations":"Manually building dispatch devices for distributed training and accidentally double-wrapping with Autodiff; helper code that wraps devices unconditionally.","solutions":["Unwrap the inner device and pass the concrete backend device instead of double-wrapping","When initializing distributed workers, use the base backend's device, not the Autodiff<B> device","Guard wrapping logic so it only applies Autodiff once"],"exampleFix":"// before\nlet dev = DispatchDevice::Autodiff(Box::new(ad_device)); // double wrap\n// after\nlet dev = ad_device.base_device(); // pass the underlying backend device","handlingStrategy":"validation","validationCode":"fn unwrap_ad_device(dev: &DispatchDevice) -> DispatchDevice {\n    match dev { DispatchDevice::Autodiff(inner) => unwrap_ad_device(inner), d => d.clone() }\n}","typeGuard":"fn is_base_device(d: &DispatchDevice) -> bool { !matches!(d, DispatchDevice::Autodiff(_)) }","tryCatchPattern":null,"preventionTips":["Never wrap Autodiff twice; use base_backend()/inner device accessors","In device-building helpers, unwrap to the concrete backend device","Assert with `matches!` that a device is a concrete backend before distributed init"],"tags":["rust","autodiff","distributed","device","panic","burn"],"backgroundTag":"autodiff-device-double-wrap","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"}