Lightning-AI/pytorch-lightning · critical · MisconfigurationException
Unknown configuration for model optimizers. Output from `mod
Error message
Unknown configuration for model optimizers. Output from `model.configure_optimizers()` should be one of:
* `Optimizer`
* [`Optimizer`]
* ([`Optimizer`], [`LRScheduler`])
* {"optimizer": `Optimizer`, (optional) "lr_scheduler": `LRScheduler`}
What it means
Lightning parses the return value of LightningModule.configure_optimizers() and only accepts an Optimizer, a list of Optimizers, a (optimizers, schedulers) tuple, or dicts with 'optimizer'/'lr_scheduler' keys. Anything else (a dict with wrong keys, a scheduler alone, a number, etc.) raises MisconfigurationException listing the accepted shapes.
Source
Thrown at src/lightning/pytorch/core/optimizer.py:239
_validate_optim_conf(optim_conf)
optimizers = [optim_conf["optimizer"]]
monitor = optim_conf.get("monitor", None)
lr_schedulers = [optim_conf["lr_scheduler"]] if "lr_scheduler" in optim_conf else []
# multiple dictionaries
elif isinstance(optim_conf, (list, tuple)) and all(isinstance(d, dict) for d in optim_conf):
for opt_dict in optim_conf:
_validate_optim_conf(opt_dict)
optimizers = [opt_dict["optimizer"] for opt_dict in optim_conf]
scheduler_dict = lambda scheduler: dict(scheduler) if isinstance(scheduler, dict) else {"scheduler": scheduler}
lr_schedulers = [
scheduler_dict(opt_dict["lr_scheduler"]) for opt_dict in optim_conf if "lr_scheduler" in opt_dict
]
# single list or tuple, multiple optimizer
elif isinstance(optim_conf, (list, tuple)) and all(isinstance(opt, Optimizable) for opt in optim_conf):
optimizers = list(optim_conf)
# unknown configuration
else:
raise MisconfigurationException(
"Unknown configuration for model optimizers."
" Output from `model.configure_optimizers()` should be one of:\n"
" * `Optimizer`\n"
" * [`Optimizer`]\n"
" * ([`Optimizer`], [`LRScheduler`])\n"
' * {"optimizer": `Optimizer`, (optional) "lr_scheduler": `LRScheduler`}\n'
)
return optimizers, lr_schedulers, monitor
def _configure_schedulers_automatic_opt(schedulers: list, monitor: Optional[str]) -> list[LRSchedulerConfig]:
"""Convert each scheduler into `LRSchedulerConfig` with relevant information, when using automatic optimization."""
lr_scheduler_configs = []
for scheduler in schedulers:
if isinstance(scheduler, dict):
# check provided keys
supported_keys = {field.name for field in fields(LRSchedulerConfig)}
extra_keys = scheduler.keys() - supported_keysView on GitHub (pinned to 9fed5c27d2)
Solutions
- Return one of the documented shapes, e.g. return (optimizers, schedulers) or {'optimizer': opt, 'lr_scheduler': sched}
- Check for typos in keys ('lr_scheduler' not 'lr_sched', not 'scheduler' at top level)
- If returning a list, ensure every element is an Optimizer — schedulers go in a separate list in a tuple
Example fix
# before
def configure_optimizers(self):
return [self.opt, self.sched]
# after
def configure_optimizers(self):
opt = torch.optim.AdamW(self.parameters(), lr=1e-3)
sched = torch.optim.lr_scheduler.StepLR(opt, 1)
return [opt], [sched] Defensive patterns
Strategy: validation
Validate before calling
from lightning.pytorch.core.optimizer import _configure_optimizers # or validate shape yourself
from torch.optim import Optimizer
conf = model.configure_optimizers()
ok = isinstance(conf, Optimizer) or (
isinstance(conf, (list, tuple)) and conf and all(isinstance(o, Optimizer) for o in conf)
) or (isinstance(conf, dict) and "optimizer" in conf)
assert ok, f"bad configure_optimizers output: {type(conf)}" Type guard
def valid_optim_conf(conf) -> bool:
from torch.optim import Optimizer
if isinstance(conf, Optimizer):
return True
if isinstance(conf, dict):
return isinstance(conf.get("optimizer"), Optimizer)
if isinstance(conf, (list, tuple)):
return all(isinstance(o, Optimizer) for o in conf)
return False Try / catch
try:
trainer.fit(model)
except MisconfigurationException as e:
if "configure_optimizers" in str(e):
fix_model_optimizers(model) # inspect return shape
raise Prevention
- Return the canonical (optimizers, schedulers) tuple shape
- Add a unit test asserting configure_optimizers returns an accepted shape
When it happens
Trigger: Returning e.g. {'optimizer': opt, 'lr_sched': sched} (typo'd key), return scheduler without optimizer, or returning a raw tuple of mismatched types from configure_optimizers.
Common situations: First-time users returning a learning-rate scheduler alone, typos in dict keys, or returning [optimizer, scheduler] as a flat list (scheduler mistaken for an optimizer).
Related errors
- The lr scheduler dict must have the key "scheduler" with its
- {seed} is not in bounds, numpy accepts from {min_seed_value}
- Expected samples ({samples}) to be greater or equal than bat
- The "interval" key in lr scheduler dict must be "step" or "e
- Some schedulers are attached with an optimizer that wasn't r
AI-assisted analysis of Lightning-AI/pytorch-lightning@9fed5c27d2 (2026-08-28).
Data as JSON: /api/errors/f8f146fc771454fe.
Report an issue: GitHub.