Lightning-AI/pytorch-lightning · error · ValueError
An optimizer should be passed only once to the `setup_optimi
Error message
An optimizer should be passed only once to the `setup_optimizers` method.
What it means
Raised when any optimizer passed to `fabric.setup_optimizers()` is already a `_FabricOptimizer`, i.e. it was already wrapped by a previous `setup`/`setup_optimizers` call. Fabric guards against double-wrapping because wrapping twice would break state loading, stepping, and strategy hooks.
Source
Thrown at src/lightning/fabric/fabric.py:1235
def _validate_setup_module(self, module: nn.Module) -> None:
self._validate_launched()
if isinstance(module, _FabricModule):
raise ValueError("A model should be passed only once to the `setup_module` method.")
def _validate_setup_optimizers(self, optimizers: Sequence[Optimizer]) -> None:
self._validate_launched()
if isinstance(self._strategy, (DeepSpeedStrategy, XLAStrategy)):
raise RuntimeError(
f"The `{type(self._strategy).__name__}` requires the model and optimizer(s) to be set up jointly"
" through `.setup(model, optimizer, ...)`."
)
if not optimizers:
raise ValueError("`setup_optimizers` requires at least one optimizer as input.")
if any(isinstance(opt, _FabricOptimizer) for opt in optimizers):
raise ValueError("An optimizer should be passed only once to the `setup_optimizers` method.")
if any(_has_meta_device_parameters_or_buffers(optimizer) for optimizer in optimizers):
raise RuntimeError(
"The optimizer has references to the model's meta-device parameters. Materializing them is"
" is currently not supported. Create the optimizer after setting up the model, then call"
" `fabric.setup_optimizers(optimizer)`."
)
def _validate_setup_dataloaders(self, dataloaders: Sequence[DataLoader]) -> None:
self._validate_launched()
if not dataloaders:
raise ValueError("`setup_dataloaders` requires at least one dataloader as input.")
if any(isinstance(dl, _FabricDataLoader) for dl in dataloaders):
raise ValueError("A dataloader should be passed only once to the `setup_dataloaders` method.")
if any(not isinstance(dl, DataLoader) for dl in dataloaders):
raise TypeError("Only PyTorch DataLoader are currently supported in `setup_dataloaders`.")View on GitHub (pinned to 9fed5c27d2)
Solutions
- Keep the unwrapped `torch.optim.Optimizer` around and pass that to setup_optimizers, discarding the wrapped return value references
- If using `fabric.setup(model, optimizer)`, do not also call `setup_optimizers`
- Audit the call order: setup the model first, create the optimizer from the setup model's parameters, then call setup_optimizers once
Example fix
# before model, optimizer = fabric.setup(model, optimizer) fabric.setup_optimizers(optimizer) # ValueError # after model, optimizer = fabric.setup(model, optimizer) # do not call setup_optimizers again
Defensive patterns
Strategy: validation
Validate before calling
from lightning.fabric.optimizers import _FabricOptimizer raw = [o for o in optimizers if not isinstance(o, _FabricOptimizer)] assert raw, 'no optimizer to set up'
Type guard
from lightning.fabric.optimizers import _FabricOptimizer
from torch.optim import Optimizer
def is_raw_optimizer(o) -> bool:
return isinstance(o, Optimizer) and not isinstance(o, _FabricOptimizer) Prevention
- Keep original (unwrapped) references to optimizers
- Adopt one setup path: either fabric.setup(model, optimizer) or split setup, never both
When it happens
Trigger: Calling `fabric.setup(model, optimizer)` and then `fabric.setup_optimizers(optimizer)` on the returned (already wrapped) optimizer; calling `setup_optimizers` twice with the same optimizer; mixing `fabric.setup(...)` and `setup_optimizers` in a migration.
Common situations: Migrating a script from `fabric.setup(model, optimizer)` to separate `setup(model)` + `setup_optimizers(optimizer)` and forgetting that setup already wraps optimizers; copy-pasting setup calls; loops that set up the same optimizer twice.
Related errors
- An optimizer should be passed only once to the `setup` metho
- `setup_optimizers` requires at least one optimizer as input.
- A dataloader should be passed only once to the `setup_datalo
- A model should be passed only once to the `setup` method.
- A model should be passed only once to the `setup_module` met
AI-assisted analysis of Lightning-AI/pytorch-lightning@9fed5c27d2 (2026-08-28).
Data as JSON: /api/errors/f5c00278ff68a070.
Report an issue: GitHub.