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.

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)

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.