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_keys

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Return one of the documented shapes, e.g. return (optimizers, schedulers) or {'optimizer': opt, 'lr_scheduler': sched}
  2. Check for typos in keys ('lr_scheduler' not 'lr_sched', not 'scheduler' at top level)
  3. 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

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


AI-assisted analysis of Lightning-AI/pytorch-lightning@9fed5c27d2 (2026-08-28). Data as JSON: /api/errors/f8f146fc771454fe. Report an issue: GitHub.