tracel-ai/burn · error

an autodiff float primitive must have an enabled autodiff co

Error message

an autodiff float primitive must have an enabled autodiff context

What it means

Generated by extract_selected_input when a float tensor input is routed to an autodiff primitive: the macro pattern-matches the DispatchAutodiffContext and requires it to be Enabled. If the selected context is Disabled (or otherwise not enabled), the operation panics because an autodiff primitive cannot run without gradient tracking active.

Source

Thrown at crates/burn-backend-extension/src/routing.rs:535

    extraction: &Extraction<'_>,
    autodiff_variant: bool,
) -> TokenStream {
    let InputKind::Tensor { kind, borrowed } = input.kind else {
        unreachable!("selected input must be a tensor")
    };
    let name = &input.name;
    let selected = format_ident!("__burn_selected");
    let dispatch_root = &extraction.paths.dispatch_root;
    let backend_alias = &extraction.paths.backend_alias;
    let context = quote!(#dispatch_root::DispatchAutodiffContext);
    assert!(
        kind == TensorKind::Float || !autodiff_variant,
        "only a float input can directly select an autodiff primitive"
    );
    let validate_context = if kind == TensorKind::Float && autodiff_variant {
        quote! {
            let #context::Enabled(_) = __burn_selected_context else {
                panic!("an autodiff float primitive must have an enabled autodiff context")
            };
        }
    } else if kind == TensorKind::Float {
        quote! {
            let #context::Disabled = __burn_selected_context else {
                panic!("an enabled float tensor must use an autodiff primitive")
            };
        }
    } else {
        TokenStream::new()
    };

    if kind == TensorKind::Float && extraction.autodiff && !autodiff_variant {
        let autodiff_trait = &extraction.paths.autodiff_trait;
        if borrowed {
            let lifted = format_ident!("__lifted_{name}");
            quote! {
                #validate_context

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Ensure the tensor's autodiff context is Enabled (create it via the autodiff backend with gradient tracking on) before the call
  2. Use the non-autodiff routing/primitive for tensors created with autodiff disabled
  3. Audit where the tensor was constructed and keep context (Enabled/Disabled) consistent with the operation's expected primitive

Example fix

// before
let tensor = Tensor::<DispatchBackend, 2>::from_data(data, &device); // context Disabled
// after
let tensor = Tensor::<AutodiffBackend, 2>::from_data(data, &device).require_grad(); // context Enabled
Defensive patterns

Strategy: type-guard

Validate before calling

fn require_enabled_context(t: &DispatchTensor) -> Result<(), String> {
    match t.autodiff {
        DispatchAutodiffContext::Enabled(_) => Ok(()),
        _ => Err("autodiff float primitive requires an enabled autodiff context".into()),
    }
}

Type guard

fn is_grad_enabled(t: &DispatchTensor) -> bool {
    matches!(t.autodiff, DispatchAutodiffContext::Enabled(_))
}

Try / catch

let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| op(&tensor)))
    .map_err(|_| "autodiff context was disabled; recreate tensor with require_grad".to_string())?

Prevention

When it happens

Trigger: Calling a dispatch operation whose selected input resolves to the Autodiff float primitive while the tensor's autodiff context is DispatchAutodiffContext::Disabled — i.e. an ad-wrapped backend tensor created without enabling the autodiff context.

Common situations: Mixing tensors created with autodiff disabled with ops that require the autodiff primitive; disabling gradient tracking globally and then invoking a routing path that targets the autodiff backend; config/state mismatch after toggling autodiff on a tensor.

Related errors


AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05). Data as JSON: /api/errors/4dd44c594b72f124. Report an issue: GitHub.