tracel-ai/burn · error

Should match at least one parameter group.

Error message

Should match at least one parameter group.

What it means

During `load_record`, each saved tensor's (parameter id, path) is matched against the optimizer's parameter groups; `optim_from_param` takes the LAST matching group via `.next_back().expect("Should match at least one parameter group.")`. If no group in the optimizer matches the parameter id/path from the record, the expect panics. This means the optimizer state being loaded belongs to a different model/config than the current optimizer's groups.

Solutions

  1. Load the optimizer record into an optimizer built from the same model structure and config that saved it.
  2. Use `to_record`/`load_record` as a matched pair from the same session/version.
  3. Regenerate the checkpoint if the model structure changed, or migrate the record's ids/paths.
  4. Add a guard comparing record param ids to `self.optimizers` group ids before calling `load_record`.

Example fix

// before
let record: OptimizerRecord = bincode::deserialize(&checkpoint_optimizer)?;
optimizer.load_record(record); // panics if model changed
// after
let record: OptimizerRecord = bincode::deserialize(&checkpoint_optimizer)?;
assert!(!record.tensors.is_empty(), "checkpoint has no optimizer tensors");
// rebuild optimizer from the checkpoint's model, then:
optimizer.load_record(record);
Defensive patterns

Strategy: validation

Validate before calling

fn record_matches(record: &OptimizerRecord, opt: &impl ToRecord) -> bool {
    // every tensor's param id should be known to the current optimizer groups
    !record.tensors.is_empty() && record.tensors.iter().all(|t| t.param_id.is_some())
}
assert!(record_matches(&record, &optimizer), "checkpoint optimizer does not match current model");

Prevention

When it happens

Trigger: Calling `load_record` with an `OptimizerRecord` whose tensor param ids/paths match none of the current optimizer's `ParamGroup`s — e.g. loading a checkpoint saved from a differently structured model, or after changing group definitions in the optimizer config.

Common situations: Restoring training from a checkpoint after renaming/restructuring modules; switching optimizer group configs between save and load; loading a record from another experiment's checkpoint; library version change that altered path or id derivation.

Related errors


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

Appendix: source

Thrown at crates/burn-optim/src/optim/module/module_optimizer.rs:195

        grads: MultiGradientsParams,
    ) -> M {
        self.step_common(lr_module.into(), module, grads.into())
    }

    fn optim_from_param(
        &self,
        id: ParamId,
        path: Option<&str>,
    ) -> (&'_ Arc<dyn DynOptimizer>, Option<GradientClipping>) {
        self.optimizers
            .iter()
            .filter_map(|val| {
                val.group
                    .matches(&id, path)
                    .then_some((&val.optim, val.grad_clipping.clone()))
            })
            .next_back()
            .expect("Should match at least one parameter group.")
    }

    /// Decompose the optimizer state into a serializable [`OptimizerRecord`].
    pub fn to_record(&self) -> OptimizerRecord {
        let mut tensors = Vec::new();
        let mut scalars = BTreeMap::new();
        let mut paths = BTreeMap::new();

        for (id, param_state) in self.param_context.iter() {
            let prefix = id.val().to_string();
            let mut sink = StateSink::default();
            param_state
                .optim
                .state_flatten(&prefix, &param_state.state, &mut sink);

            // Persist the parameter rank explicitly so the state can be reconstructed even when it
            // carries no tensors, and without inferring the rank from tensor shapes.
            scalars.insert(

View on GitHub (pinned to d16f7ba2ed)