tracel-ai/burn · error

unimplemented!("float_scatter with update is not…

Error message

unimplemented!("float_scatter with {other:?} update is not implemented")

What it means

In the autodiff backend's float_scatter (crates/burn-autodiff/src/ops/tensor.rs:1262), only Add/Sub/Mul update ops are matched for the scatter's IndexingUpdateOp; any other update op falls into the catch-all arm and panics with unimplemented!("float_scatter with {other:?} update is not implemented").

Solutions

  1. Restrict scatter updates to Add, Sub, or Mul inside training (autodiff) code.
  2. Perform unsupported scatter updates outside the autodiff graph (e.g. under no_grad / on non-grad tensors).
  3. Add a gradient rule for the missing IndexingUpdateOp in burn-autodiff and upstream it.

Example fix

// before
tensor.scatter(1, indices, value, IndexingUpdateOp::Assign);
// after
tensor.scatter(1, indices, value, IndexingUpdateOp::Add);
Defensive patterns

Strategy: validation

Validate before calling

assert!(matches!(op, IndexingUpdateOp::Add | IndexingUpdateOp::Sub | IndexingUpdateOp::Mul), "autodiff float_scatter only supports Add/Sub/Mul");

Prevention

When it happens

Trigger: Calling Tensor::scatter with an IndexingUpdateOp other than Add, Sub, or Mul while running under burn-autodiff (training mode).

Common situations: Using exotic scatter update semantics (e.g. custom assignment/max updates) during gradient computation; forward-only code on the base backend may work but the autodiff wrapper panics.

Related errors


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

Appendix: source

Thrown at crates/burn-autodiff/src/ops/tensor.rs:1262

                            B::float_scatter(
                                dim,
                                tensor.primitive,
                                indices,
                                value.primitive,
                                IndexingUpdateOp::Mul,
                            ),
                        )
                    }
                    OpsKind::UnTracked(prep) => prep.finish(B::float_scatter(
                        dim,
                        tensor.primitive,
                        indices,
                        value.primitive,
                        IndexingUpdateOp::Mul,
                    )),
                }
            }
            other => unimplemented!("float_scatter with {other:?} update is not implemented"),
        }
    }

    fn float_scatter_nd(
        data: FloatTensor<Self>,
        indices: IntTensor<B>,
        values: FloatTensor<Self>,
        reduction: burn_backend::tensor::IndexingUpdateOp,
    ) -> FloatTensor<Self> {
        use burn_backend::tensor::IndexingUpdateOp;

        match reduction {
            IndexingUpdateOp::Add => {
                #[derive(Debug)]
                struct ScatterNdAdd;

                impl<B: Backend> Backward<B, 2> for ScatterNdAdd {
                    type State = IntTensor<B>;

View on GitHub (pinned to d16f7ba2ed)