{"record":{"id":"2733819389ac1a6c","repo":"tracel-ai/burn","slug":"should-have-at-least-one-optimizer","errorCode":null,"errorMessage":"Should have at least one optimizer","messagePattern":"Should have at least one optimizer","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-optim/src/optim/module/module_optimizer.rs","lineNumber":92,"sourceCode":"                grad_clipping: None,\n            }],\n        }\n    }\n}\n\nimpl ModuleOptimizer {\n    /// Check if the optimizer has gradient clipping.\n    /// If there are multiple optimizers, checks if any group has gradient clipping.\n    pub fn has_gradient_clipping(&self) -> bool {\n        self.optimizers.iter().any(|g| g.grad_clipping.is_some())\n    }\n\n    /// Access the gradient clipping.\n    /// If there are multiple optimizers, returns the first optimizer's [GradientClipping].\n    pub fn grad_clipping(&self) -> Option<&GradientClipping> {\n        self.optimizers\n            .first()\n            .expect(\"Should have at least one optimizer\")\n            .grad_clipping\n            .as_ref()\n    }\n\n    /// Sets the gradient clipping.\n    /// If there are multiple optimizers, assigns it to the first one.\n    ///\n    /// # Arguments\n    ///\n    /// * `gradient_clipping` - The gradient clipping.\n    ///\n    /// # Returns\n    ///\n    /// The optimizer.\n    pub fn with_grad_clipping(mut self, gradient_clipping: GradientClipping) -> Self {\n        self.optimizers\n            .first_mut()\n            .expect(\"Should have at least one optimizer\")","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-optim/src/optim/module/module_optimizer.rs#L74-L110","documentation":"`grad_clipping()` on a module-level optimizer expects the internal `optimizers` vector to be non-empty and calls `.first().expect(\"Should have at least one optimizer\")`. If the `ModuleOptimizer` was constructed without any per-parameter-group optimizers registered, the unwrap panics instead of returning an Option. This is an internal invariant check: a module optimizer with zero optimizers is a construction bug, not a runtime condition.","triggerScenarios":"Calling `grad_clipping()` on a `ModuleOptimizer` whose `optimizers` vec is empty — i.e. the optimizer was created via a path that never registered any parameter-group optimizers (e.g. a default/degenerate `OptimizerAdapter` built without groups, or a record-loading path that left the vec empty).","commonSituations":"Constructing a `ModuleOptimizer` manually with an empty optimizer list; deserializing/loading an optimizer state that produced no groups; version or config changes that removed all parameter groups before the clipping accessor is queried (e.g. from a learning-rate/clip scheduler reading grad clipping each step).","solutions":["Ensure the `ModuleOptimizer` is built through its normal constructor/init path so every parameter group registers an optimizer before `grad_clipping()` is called.","If building manually, guarantee at least one entry is pushed into `optimizers` before use.","Check that the optimizer record/state you loaded actually contains parameter groups (see `to_record`/`load_record`).","Replace direct construction with `OptimizerAdapter::from_optimizer` style APIs that derive groups from the model."],"exampleFix":"// before\nlet opt: ModuleOptimizer<MyOpt> = ModuleOptimizer { optimizers: vec![] };\nopt.grad_clipping(); // panics\n// after\nlet opt = OptimizerAdapter::from_optimizer(my_opt, config); // registers groups\nopt.grad_clipping(); // Ok(None) or Some(&clip)","handlingStrategy":"validation","validationCode":"fn has_optimizers<M>(opt: &ModuleOptimizer<M>) -> bool { !opt.is_empty() } // or check group count via to_record()\nassert!(has_optimizers(&opt), \"optimizer has no parameter groups\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always create ModuleOptimizer through its official constructor/init path, never with an empty optimizers vec","Call with_grad_clipping/grad_clipping only after optimizer init with the model","Verify loaded records produce non-empty groups before use"],"tags":["rust","panic","optimizer","burn"],"backgroundTag":"empty-optimizer-state","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}