tracel-ai/burn · error
Autodiff should not wrap an autodiff tensor.
Error message
Autodiff should not wrap an autodiff tensor.
What it means
DispatchTensorKind::Autodiff is a wrapper that must contain exactly one concrete backend tensor (NdArray, LibTorch, etc.). If backward() encounters an Autodiff kind wrapped inside another Autodiff kind, the internal invariant 'no double autodiff wrapping' is violated and the code panics. Hitting it indicates a tensor-construction bug in dispatch code, not a user-recoverable condition.
Source
Thrown at crates/burn-dispatch/src/backend.rs:348
match kind {
DispatchTensorKind::Autodiff(tensor) => match *tensor {
#[cfg(cube_backend)]
DispatchTensorKind::Cube(tensor) => tensor.autodiff().backward(),
#[cfg(any(feature = "flex", default_backend))]
DispatchTensorKind::Flex(tensor) => tensor.autodiff().backward(),
#[cfg(feature = "ndarray")]
DispatchTensorKind::NdArray(tensor) => tensor.autodiff().backward(),
#[cfg(feature = "tch")]
DispatchTensorKind::LibTorch(tensor) => tensor.autodiff().backward(),
#[cfg(feature = "remote")]
DispatchTensorKind::Remote(tensor) => tensor.autodiff().backward(),
#[cfg(feature = "capture")]
DispatchTensorKind::Capture(_) => {
panic!("Capture tensors do not support autodiff")
}
DispatchTensorKind::Autodiff(_) => {
panic!("Autodiff should not wrap an autodiff tensor.")
}
},
_ => panic!("Requires autodiff tensor."),
}
}
fn grad(tensor: &DispatchTensor, grads: &Self::Gradients) -> Option<DispatchTensor> {
let DispatchTensor { kind, .. } = tensor;
let grad: Option<DispatchTensorKind> = match &kind {
DispatchTensorKind::Autodiff(inner_kind) => match &**inner_kind {
#[cfg(cube_backend)]
DispatchTensorKind::Cube(tensor) => tensor
.as_autodiff()
.grad(grads)
.map(|t| DispatchTensorKind::Cube(crate::BackendTensor::Float(t))),
#[cfg(any(feature = "flex", default_backend))]
DispatchTensorKind::Flex(tensor) => tensor
.as_autodiff()View on GitHub (pinned to d16f7ba2ed)
Solutions
- Unwrap to the inner backend tensor before calling backward() (use AutodiffBackend::inner)
- Audit code that constructs DispatchTensorKind::Autodiff so it never wraps an already-wrapped tensor
- Update burn-dispatch and dependent crates to matching versions
Example fix
// before let grads = Dispatch::backward(double_wrapped_tensor); // after let inner_tensor = Dispatch::inner(double_wrapped_tensor); let grads = Dispatch::backward(inner_tensor);
Defensive patterns
Strategy: type-guard
Validate before calling
fn ensure_single_autodiff_wrap(t: &DispatchTensor) -> Result<(), String> {
if let DispatchTensorKind::Autodiff(inner) = &t.kind {
if matches!(**inner, DispatchTensorKind::Autodiff(_)) {
return Err("tensor is double-wrapped in Autodiff".into());
}
}
Ok(())
} Type guard
fn is_double_wrapped(t: &DispatchTensor) -> bool {
matches!(&t.kind, DispatchTensorKind::Autodiff(inner)
if matches!(**inner, DispatchTensorKind::Autodiff(_)))
} Try / catch
let result = std::panic::catch_unwind(AssertUnwindSafe(|| Dispatch::backward(t)));
if result.is_err() { eprintln!("double autodiff wrap detected"); } Prevention
- Never wrap an already-wrapped DispatchTensor in Autodiff again
- Use inner()/AutodiffBackend::inner() to unwrap before re-wrapping
- Pin all burn crates to the same version
When it happens
Trigger: Dispatch::backward() on a tensor whose outer kind is Autodiff and whose inner kind is also Autodiff — i.e. Autodiff(Autodiff(...)) — typically from calling backward() on a tensor that already went through inner()/autodiff unwrapping incorrectly.
Common situations: Custom backend glue or plugin code that wraps an already-autodiffed DispatchTensor again; mixing tensor values from different dispatch layers; library version mismatch where wrapping logic changed.
Related errors
- an autodiff float primitive must have an enabled autodiff co
- an enabled float tensor must use an autodiff primitive
- Capture tensors do not support autodiff
- Requires autodiff tensor.
- Autodiff float tensor is on the wrong backend (expected {bac
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/38c5ff15ce6533cc.
Report an issue: GitHub.