tracel-ai/burn · error
autodiff float input reached concrete dispatch
Error message
autodiff float input reached concrete dispatch
What it means
Generated as the `invalid_autodiff_float` arm: when an operation is routed to the concrete (non-autodiff) backend, an input arriving under `DispatchTensorKind::Autodiff` for a float kind is rejected. An autodiff (gradient-tracking) float tensor cannot be consumed by a concrete backend primitive, so the codegen panics with this message to prevent silently dropping gradient tracking.
Source
Thrown at crates/burn-backend-extension/src/routing.rs:788
match tensor {
#backend_tensor::Autodiff(tensor) => #backend_tensor::Float(tensor),
_ => panic!("only float tensors may use an autodiff primitive"),
}
}
#dispatch_kind::#backend(tensor) => match tensor {
#backend_tensor::Float(tensor) => {
let #context::Disabled = __input_context else {
panic!("an enabled float tensor must use an autodiff primitive")
};
#backend_tensor::Float(
<#backend_alias as #autodiff_trait>::from_inner(tensor)
)
}
#backend_tensor::Int(tensor) => #backend_tensor::Int(tensor),
#backend_tensor::Bool(tensor) => #backend_tensor::Bool(tensor),
#backend_tensor::Quantized(tensor) => #backend_tensor::Quantized(tensor),
#backend_tensor::Autodiff(_) => {
panic!("autodiff float input reached concrete dispatch")
}
},
#[allow(unreachable_patterns)]
_ => #mismatch,
}
});
}
} else {
let target = ir::with_backend(ty, quote!(#backend_root::#backend));
quote! {
let #name = <#target as #extension_trait<#backend_root::#backend>>::map_from_dispatch(
#name,
|__tensor| {
match __tensor.kind {
#dispatch_kind::#backend(tensor) => tensor,
#[allow(unreachable_patterns)]
_ => #mismatch,
}View on GitHub (pinned to d16f7ba2ed)
Solutions
- Detach/convert the autodiff tensor to its inner concrete float tensor before the call (e.g. via the non-autodiff repr)
- Route the call to the autodiff variant of the op so Autodiff inputs are accepted
- Restructure so differentiating tensors never leave the tracked region into concrete-only ops
Example fix
// before let y = concrete_only_op::<B>(ad_tensor); // panics: autodiff float input reached concrete dispatch // after let inner = ad_tensor.inner(); // strip autodiff wrapper let y = concrete_only_op::<B>(inner);
Defensive patterns
Strategy: type-guard
Validate before calling
if let DispatchTensorKind::Autodiff(_) = t.kind { /* not safe for concrete-only ops */ detach_or_reroute(); } Type guard
fn is_concrete_dispatch(t: &DispatchTensor) -> bool { !matches!(&t.kind, DispatchTensorKind::Autodiff(_)) } Prevention
- Keep differentiating tensors inside grad-tracked call paths
- Detach autodiff tensors before handing them to inference/concrete-only ops
- Ensure routed signatures include autodiff variants when tensors may be tracking gradients
When it happens
Trigger: Calling a routed op compiled for the concrete backend (no autodiff lifting) with a tensor wrapped in the Autodiff dispatch kind — e.g. mixing differentiating and non-differentiating paths, or calling a concrete-only extension op inside a backward pass.
Common situations: Calling inference-only routed ops with training tensors; routing signatures missing the autodiff parameter so the concrete variant was generated; handing tensors out of a `grad` closure into non-autodiff code paths.
Related errors
- only float tensors may use an autodiff primitive
- Expected autodiff-wrapped float tensor for backend {backend}
- autodiff context requires the `autodiff` feature
- Operation not marked for autodiff.
- an autodiff float primitive must have an enabled autodiff co
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/12d52533157584bc.
Report an issue: GitHub.