{"record":{"id":"3e797bbd72e929d8","repo":"tracel-ai/burn","slug":"autodiff-should-not-wrap-an-autodiff-tensor","errorCode":null,"errorMessage":"Autodiff should not wrap an autodiff tensor.","messagePattern":"Autodiff should not wrap an autodiff tensor\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-backend-extension/src/dispatch.rs","lineNumber":197,"sourceCode":"    source_kind: TokenStream,\n    inner_kind: TokenStream,\n) -> TokenStream {\n    let float_inputs = float_input_presence(operation, source);\n    let backends = dispatch_backends();\n    let source_is_non_float = source.is_some_and(|source| {\n        matches!(\n            source.kind,\n            InputKind::Tensor { kind, .. } if kind != TensorKind::Float\n        )\n    });\n    let paths = routing::RoutingPaths::dispatch();\n    let selected =\n        source.map(|_| syn::Ident::new(\"__burn_selected\", proc_macro2::Span::call_site()));\n    let autodiff_match = (!source_is_non_float).then(|| routing::AutodiffKindMatch {\n        cfg_attr: Some(quote!(#[cfg(feature = \"autodiff\")])),\n        inner_kind,\n        nested_autodiff: Some(quote! {\n            panic!(\"Autodiff should not wrap an autodiff tensor.\")\n        }),\n        fallback: quote!(panic!(\"unsupported dispatch backend\")),\n    });\n    let arms = routing::backend_kind_arms(\n        &paths,\n        &backends,\n        selected.as_ref(),\n        autodiff_match,\n        |_, backend, autodiff| {\n            backend_route_body(backend, operation, &float_inputs, autodiff, source)\n        },\n    );\n    let direct_arms = arms.concrete;\n    let autodiff_route = if source_is_non_float {\n        quote! {\n            #[cfg(feature = \"autodiff\")]\n            crate::DispatchTensorKind::Autodiff(_) => {\n                panic!(\"only float tensors may use an autodiff primitive\")","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-backend-extension/src/dispatch.rs#L179-L215","documentation":"This panic is emitted by code generated by the burn-backend-extension dispatch macro. The AutodiffKindMatch route is generated such that if the runtime dispatch tensor already carries an Autodiff kind, wrapping it again in autodiff is invalid (autodiff must wrap a plain backend, never another autodiff backend), so the generated match arm panics.","triggerScenarios":"Passing a tensor already typed as Autodiff<B, C> through the dispatch machinery that tries to re-wrap it as autodiff (nested autodiff); misconfigured backend generics that resolve the autodiff arm twice.","commonSituations":"Double-wrapping backends like Autodiff<Autodiff<Wgpu>>; macro-generated dispatch functions receiving autodiff tensors from an outer layer; backend-agnostic code compiled with the autodiff feature fed already-tracked tensors.","solutions":["Remove the double wrap: use Autodiff<B> once at the outermost boundary only","Pass the inner (non-autodiff) tensor into the dispatch call, unwrapping any AutodiffTensor first","Disable the autodiff feature for the dispatch macro invocation if the call site is not a training boundary","Fix generic bounds so autodiff wrapping happens only where the kind is not already Autodiff"],"exampleFix":"// before\nlet x = AutodiffTensor::from(AutodiffTensor::from(inner_tensor)); // nested\n// after\nlet x = AutodiffTensor::from(inner_tensor);","handlingStrategy":"type-guard","validationCode":"// Ensure you never double-wrap: if T is already Autodiff<...>, do not wrap again\nfn assert_single_wrap<B: Backend>(_t: &AutodiffTensor<B>) {} // compile-time: B must be a plain backend","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap the innermost concrete backend only once: Autodiff<Wgpu>, never Autodiff<Autodiff<Wgpu>>","Unwrap AutodiffTensor to its inner tensor before dispatch calls","Keep autodiff wrapping at a single boundary in the codebase","Review macro invocations so nested_autodiff arms are not hit"],"tags":["rust","autodiff","dispatch-macro","nested-autodiff"],"backgroundTag":"nested-autodiff-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"}