tracel-ai/burn · error
Tensor is on the wrong backend (expected {backend}).
Error message
Tensor is on the wrong backend (expected {backend}). What it means
The burn-dispatch `unwrap_vec!` macro converts dispatch tensors into backend-specific tensors. When a tensor's DispatchTensorKind variant does not match the backend being unwrapped, the library panics with 'Tensor is on the wrong backend'. This guards against mixing tensors created by different backends in one operation.
Source
Thrown at crates/burn-dispatch/src/macros.rs:396
($kind:ident, $inner_fn:ident, $tensor:expr, $device:expr, $to_device:ident, |$inner:ident, $device_ident:ident| $body:expr) => {
backend_matrix!(
float_to_device_arms,
$tensor,
$device,
$to_device,
|$inner, $device_ident| $body
)
};
}
/// Unwraps a `Vec<DispatchTensor>` for a known backend.
macro_rules! unwrap_vec {
($Backend:ident, $vec:expr, $kind:ident) => {
$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)
),
},View on GitHub (pinned to d16f7ba2ed)
Solutions
- Ensure every tensor passed to the operation was created by the same backend as the operation's target backend
- Call `.to_device(...)` / recreate the tensor on the target backend before the call
- Check that you are not mixing an Autodiff-wrapped tensor with a primitive tensor where the unwrap expects the primitive variant
Example fix
// before let out = my_op(vec![cpu_tensor]); // running under Wgpu backend // after let out = my_op(vec![cpu_tensor.to_device(&wgpu_device)]); // convert to the active backend
Defensive patterns
Strategy: validation
Validate before calling
fn assert_same_backend<B: Backend>(t: &burn::tensor::Tensor<B, D>) -> bool { /* ensure tensor's backend type parameter equals the op's backend */ true } // in Rust this is enforced statically via the B type parameter — keep all tensors as Tensor<B, _> for one B Prevention
- Keep one backend type alias (type B = Wgpu;) and use it for every tensor
- Use `.to_device()` when moving between devices
- Never mix tensors from different Backend implementations in one call
When it happens
Trigger: Calling a dispatch-level tensor API (e.g. via Autodiff backend, ad_enabled, or memory_persistent_allocations paths) passing a vector of tensors where at least one tensor was created on a different backend than the one the macro was instantiated for (e.g. a Cpu tensor given to a Wgpu-dispatched op).
Common situations: Moving tensors between devices/backends and forgetting to convert them; passing a tensor from a non-autodiff backend into an autodiff-wrapped graph; storing tensors across backend switches in cached state.
Related errors
- Autodiff float tensor is on the wrong backend (expected {bac
- capture tensor operations must run inside CaptureDevice::cap
- Expected autodiff-wrapped float tensor for backend {backend}
- Distributed operations are not supported for device {other:?
- Autodiff should not wrap an autodiff device.
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/02fac4159961edd2.
Report an issue: GitHub.