tracel-ai/burn · error
Autodiff float tensor is on the wrong backend (expected {bac
Error message
Autodiff float tensor is on the wrong backend (expected {backend}). What it means
The `@autodiff` arm of the unwrap macro first unwraps an Autodiff-wrapped tensor kind, then expects the inner tensor to match the concrete backend. If the inner primitive is from a different backend, it panics with 'Autodiff float tensor is on the wrong backend'.
Source
Thrown at crates/burn-dispatch/src/macros.rs:410
$vec.into_iter()
.map(|t| match t.kind {
$crate::DispatchTensorKind::$Backend(inner) => inner.$kind(),
#[allow(unreachable_patterns)]
_ => panic!(
"Tensor is on the wrong backend (expected {}).",
stringify!($Backend)
),
})
.collect::<Vec<_>>()
};
// Autodiff-wrapped backend
(@autodiff $Backend:ident, $vec:expr, $kind:ident) => {
$vec.into_iter()
.map(|t| match t.kind {
$crate::DispatchTensorKind::Autodiff(inner) => match *inner {
$crate::DispatchTensorKind::$Backend(inner) => inner.$kind(),
_ => panic!(
"Autodiff float tensor is on the wrong backend (expected {}).",
stringify!($Backend)
),
},
_ => panic!(
"Expected autodiff-wrapped float tensor for backend {}.",
stringify!($Backend)
),
})
.collect::<Vec<_>>()
};
}
/// Match arm generator for `transaction_op`.
macro_rules! transaction_op_arms {
($tx:ident, $first:expr; $([$Backend:ident, $cfg:meta]),*) => {{
match &$first.kind {
// Autodiff arm firstView on GitHub (pinned to d16f7ba2ed)
Solutions
- Build all autodiff tensors from the same inner backend that Autodiff<B> wraps
- Recreate the tensor on the wrapped backend before passing it in
- Verify the generic B parameter of your Autodiff<B> backend matches the tensors you pass
Example fix
// before let ad = AutodiffTensor::from(wgpu_tensor); // used inside Autodiff<Cpu> graph // after let ad = AutodiffTensor::from(cpu_tensor); // inner tensor matches Autodiff<Cpu>
Defensive patterns
Strategy: validation
Validate before calling
fn check_ad_backend<B: AutodiffBackend>(t: &burn::tensor::Tensor<B, D>) -> bool { B::InnerBackend::device(&t.device()).is_ok() } // ensure the tensor belongs to Autodiff<B>'s inner backend Type guard
fn is_ad_of_b<B: Backend>(t: &AdBackend<B>::Tensor<D>) -> bool { true } // rely on Rust generics: AdBackend<B> tensors are typed, so wrong-backend tensors won't compile Prevention
- Use type aliases: type AdB = Autodiff<Wgpu>; and type AdTensor<D> = burn::tensor::Tensor<AdB, D>;
- Only construct autodiff tensors from B::InnerBackend tensors
- Don't convert autodiff tensors to primitives and back across backends
When it happens
Trigger: Passing an Autodiff tensor whose inner backend tensor is not of the expected backend kind into an unwrap that requires the concrete backend (e.g. an Autodiff<Wgpu> tensor supplied to a Cpu-targeted operation).
Common situations: Wrapping one backend in Autodiff but passing tensors built from another backend into the training graph; constructing an Autodiff tensor manually from the wrong primitives.
Related errors
- Tensor is on the wrong backend (expected {backend}).
- Expected autodiff-wrapped float tensor for backend {backend}
- Autodiff should not wrap an autodiff device.
- an autodiff float primitive must have an enabled autodiff co
- autodiff context requires the `autodiff` feature
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/df50eea58d863c86.
Report an issue: GitHub.