{"record":{"id":"8492c39e20ac3252","repo":"tracel-ai/burn","slug":"input-tensor-is-on-the-wrong-backend","errorCode":null,"errorMessage":"input tensor `{}` is on the wrong backend","messagePattern":"input tensor `(.+?)` is on the wrong backend","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-backend-extension/src/routing.rs","lineNumber":673,"sourceCode":"            #dispatch_kind::Autodiff(_) => panic!(\"autodiff float input reached concrete dispatch\"),\n        }\n    });\n    let invalid_autodiff_kind = extraction.has_autodiff_variant.then(|| quote! {\n        #ad_cfg\n        #dispatch_kind::Autodiff(_) => panic!(\"only float tensors may use an autodiff primitive\"),\n    });\n\n    if kind == TensorKind::Float && extraction.autodiff {\n        if borrowed {\n            let lifted = format_ident!(\"__lifted_{name}\");\n            quote! {\n                let #lifted;\n                let #name = match &#name.kind {\n                    #dispatch_kind::Autodiff(__inner) => {\n                        #validate_enabled_float\n                        match __inner.as_ref() {\n                            #dispatch_kind::#backend(__inner) => __inner.as_autodiff(),\n                            _ => panic!(\"input tensor `{}` is on the wrong backend\", stringify!(#name)),\n                        }\n                    }\n                    #dispatch_kind::#backend(__inner) => {\n                        #validate_disabled_float\n                        #lifted = <#backend_alias as #autodiff_trait>::from_inner(__inner.as_float().clone());\n                        &#lifted\n                    }\n                    _ => panic!(\"input tensor `{}` is on the wrong backend\", stringify!(#name)),\n                };\n            }\n        } else {\n            quote! {\n                let #name = match #name.kind {\n                    #dispatch_kind::Autodiff(__inner) => {\n                        #validate_enabled_float\n                        match *__inner {\n                            #dispatch_kind::#backend(__inner) => __inner.autodiff(),\n                            _ => panic!(\"input tensor `{}` is on the wrong backend\", stringify!(#name)),","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-backend-extension/src/routing.rs#L655-L691","documentation":"Generated by extract_tensor (borrowed float + autodiff path): the input tensor's kind is Autodiff, but its inner device does not match the concrete backend the operation was expanded for, so the macro panics naming the tensor. The dispatch macro generates per-backend code; at runtime the tensor's actual inner backend must equal that backend.","triggerScenarios":"Calling a dispatch operation with a tensor whose inner backend differs from the backend the call was dispatched/compiled to — e.g. a Cpu tensor passed to a Wgpu-targeted expansion, wrapped in Autodiff.","commonSituations":"Mixing tensors created on different backend devices in one op; moving a model/tensor between backends without re-dispatching; multi-backend setups (cpu + wgpu + cuda) where tensors come from the wrong device.","solutions":["Ensure all tensor arguments of an operation come from the same backend/device as the dispatch target","Move/convert the tensor to the expected backend before the call (re-create it on the target device)","Check which backend the failing op was expanded for and align tensor creation accordingly"],"exampleFix":"// before\nlet a = Tensor::<Autodiff<Cpu>, 2>::ones(...);\nlet b = Tensor::<Autodiff<Wgpu>, 2>::ones(...);\nmix(a, b); // panic\n// after\nlet b = Tensor::<Autodiff<Cpu>, 2>::ones(...); // same backend as a\nmix(a, b);","handlingStrategy":"validation","validationCode":"fn ensure_same_backend(a: &DispatchTensor, b: &DispatchTensor) -> Result<(), String> {\n    if std::mem::discriminant(&a.kind) != std::mem::discriminant(&b.kind) {\n        return Err(\"input tensors are on different backends\".into());\n    }\n    Ok(())\n}","typeGuard":"fn inner_is_expected_backend(t: &DispatchTensor) -> bool {\n    match &t.kind {\n        DispatchTensorKind::Autodiff(inner) => matches!(inner.as_ref(), DispatchTensorKind::Cpu(_)),\n        DispatchTensorKind::Cpu(_) => true,\n        _ => false,\n    }\n}","tryCatchPattern":"let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| mix(&a, &b)))\n    .map_err(|_| \"wrong backend for input tensor; recreate it on the dispatch device\".to_string())?","preventionTips":["Create all tensor arguments for an op on the same backend/device","Convert tensors across backends explicitly before mixed operations","Log each tensor's backend at op boundaries in multi-backend apps"],"tags":["rust","backend","device-mismatch","autodiff"],"backgroundTag":"backend-device-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"}