tracel-ai/burn · error

Can't differentiate embedding backward.

Error message

Can't differentiate embedding backward.

What it means

The BackendRouter's QTensorOps implementation is entirely stubbed: q_from_data (creating a quantized tensor from raw data) panics with unimplemented!. The router does not yet support creating quantized tensors directly from data.

Source

Thrown at crates/burn-autodiff/src/ops/module.rs:60

        match Embedding
            .prepare::<C>([weights.node])
            .compute_bound()
            .stateful()
        {
            OpsKind::Tracked(prep) => prep.finish(
                (weights.primitive.clone(), indices.clone()),
                B::embedding(weights.primitive, indices),
            ),
            OpsKind::UnTracked(prep) => prep.finish(B::embedding(weights.primitive, indices)),
        }
    }

    fn embedding_backward(
        _weights: AutodiffTensor<B>,
        _output: AutodiffTensor<B>,
        _indices: IntTensor<B>,
    ) -> AutodiffTensor<B> {
        panic!("Can't differentiate embedding backward.");
    }

    fn linear(
        x: AutodiffTensor<B>,
        weight: AutodiffTensor<B>,
        bias: Option<AutodiffTensor<B>>,
    ) -> AutodiffTensor<B> {
        #[derive(Debug)]
        struct LinearWithBias;
        #[derive(Debug)]
        struct LinearNoBias;

        impl<B: Backend> Backward<B, 3> for LinearWithBias {
            type State = (Option<NodeId>, Option<NodeId>);

            fn backward(
                self,
                ops: Ops<Self::State, 3>,

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Run quantized workloads on a concrete backend that implements QTensorOps, not BackendRouter.
  2. Quantize at runtime instead: create a float tensor from data, then quantize it with a backend supporting quantize (note: router quantize is also stubbed, so this requires a concrete backend).
  3. Upstream/downgrade: check burn version for router quantization support.

Example fix

// before
let q = BackendRouter::<R>::q_from_data(data, &device); // panics
// after
let f = B::float_from_data(data, &device);
let q = B::quantize(f, &scheme, qparams); // on a concrete backend
Defensive patterns

Strategy: fallback

Validate before calling

fn supports_router_qtensor<B: Backend>() -> bool {
    // BackendRouter's QTensorOps is stubbed; require a concrete backend
    false
}

Type guard

fn is_qfloat(dtype: &burn_tensor::DType) -> bool {
    matches!(dtype, burn_tensor::DType::QFloat(_))
}

Try / catch

let q = std::panic::catch_unwind(|| B::q_from_data(data.clone(), &device))
    .map_err(|_| anyhow::anyhow!("q_from_data unsupported on router; use a concrete backend"))?;

Prevention

When it happens

Trigger: Calling q_from_data::<BackendRouter<...>>(data, device) — e.g. deserializing a quantized checkpoint or constructing a quantized tensor from stored TensorData on a routed backend.

Common situations: Loading quantized models from disk on a router backend; code generic over Backend that happens to resolve to BackendRouter; quantization support gaps between concrete backends and the router.

Related errors


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