tracel-ai/burn · error

Should be float, got autodiff

Error message

Should be float, got autodiff

What it means

BackendTensor::float() panics with this message when called on an Autodiff tensor (only compiled with the "autodiff" feature). The method returns a plain float primitive; an autodiff-wrapped tensor must be unwrapped via .inner() or accessed through autodiff-aware APIs, so passing it to .float() is a variant-handling bug.

Source

Thrown at crates/burn-dispatch/src/tensor.rs:45

    /// Bool tensor handle.
    Bool(B::BoolTensorPrimitive),
    /// Quantized tensor handle.
    Quantized(B::QuantizedTensorPrimitive),
    #[cfg(feature = "autodiff")]
    /// Autodiff float tensor handle.
    Autodiff(FloatTensor<Autodiff<B>>),
}

impl<B: Backend> BackendTensor<B> {
    /// Returns the inner float tensor primitive.
    pub fn float(self) -> B::FloatTensorPrimitive {
        match self {
            BackendTensor::Float(tensor) => tensor,
            BackendTensor::Int(_) => panic!("Should be float, got int"),
            BackendTensor::Bool(_) => panic!("Should be float, got bool"),
            BackendTensor::Quantized(_) => panic!("Should be float, got quantized"),
            #[cfg(feature = "autodiff")]
            BackendTensor::Autodiff(_) => panic!("Should be float, got autodiff"),
        }
    }
    /// Returns the inner float tensor primitive.
    pub fn as_float(&self) -> &B::FloatTensorPrimitive {
        match self {
            BackendTensor::Float(tensor) => tensor,
            BackendTensor::Int(_) => panic!("Should be float, got int"),
            BackendTensor::Bool(_) => panic!("Should be float, got bool"),
            BackendTensor::Quantized(_) => panic!("Should be float, got quantized"),
            #[cfg(feature = "autodiff")]
            BackendTensor::Autodiff(_) => panic!("Should be float, got autodiff"),
        }
    }

    /// Returns the inner int tensor primitive.
    pub fn int(self) -> B::IntTensorPrimitive {
        match self {
            BackendTensor::Int(tensor) => tensor,

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Strip the autodiff wrapper first with .inner() before calling .float().
  2. Match on the BackendTensor variant and recurse into the inner tensor for the Autodiff case.
  3. Use autodiff-aware accessors/ops when gradient tracking is required rather than extracting the raw float primitive.
  4. Check backend selection: if autodiff shouldn't be active, build tensors with the base backend instead of the Autodiff wrapper.

Example fix

// before
let f = tensor.float(); // panics: Autodiff
// after
let f = match tensor {
    BackendTensor::Autodiff(a) => BackendTensor::Float(a.inner()).float(),
    t => t.float(),
};
Defensive patterns

Strategy: type-guard

Validate before calling

// before calling .float()
if let BackendTensor::Autodiff(_) = &tensor {
    // unwrap with .inner() first
}

Type guard

fn is_autodiff_tensor<B: Backend>(t: &BackendTensor<B>) -> bool {
    matches!(t, BackendTensor::Autodiff(_))
}

Try / catch

// guard before extraction
let f = match tensor {
    BackendTensor::Autodiff(a) => BackendTensor::Float(a.inner()).float(),
    t => t.float(),
};

Prevention

When it happens

Trigger: Calling BackendTensor::float() on a tensor holding BackendTensor::Autodiff(_) — an autodiff-wrapped primitive (feature "autodiff" enabled) reaching float-only code without being stripped first.

Common situations: Forgetting to call .inner() (which strips autodiff wrappers) before dtype accessors; mixing autodiff-enabled and non-autodiff backends where generic code assumes plain primitives.

Related errors


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