Lightning-AI/pytorch-lightning · critical · MisconfigurationException

The lr scheduler dict must have the key "scheduler" with its

Error message

The lr scheduler dict must have the key "scheduler" with its item being an lr scheduler

What it means

When a learning-rate scheduler is provided as a dict in configure_optimizers output, the dict must contain the key "scheduler" mapping to the scheduler object. After unsupported keys are stripped (with a warning), a missing "scheduler" key raises MisconfigurationException.

Source

Thrown at src/lightning/pytorch/core/optimizer.py:266


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
            if extra_keys:
                rank_zero_warn(
                    f"Found unsupported keys in the lr scheduler dict: {extra_keys}."
                    " HINT: remove them from the output of `configure_optimizers`.",
                    category=RuntimeWarning,
                )
                scheduler = {k: v for k, v in scheduler.items() if k in supported_keys}
            if "scheduler" not in scheduler:
                raise MisconfigurationException(
                    'The lr scheduler dict must have the key "scheduler" with its item being an lr scheduler'
                )
            if "interval" in scheduler and scheduler["interval"] not in ("step", "epoch"):
                raise MisconfigurationException(
                    'The "interval" key in lr scheduler dict must be "step" or "epoch"'
                    f' but is "{scheduler["interval"]}"'
                )
            scheduler["reduce_on_plateau"] = scheduler.get(
                "reduce_on_plateau", isinstance(scheduler["scheduler"], optim.lr_scheduler.ReduceLROnPlateau)
            )
            if scheduler["reduce_on_plateau"] and scheduler.get("monitor") is None:
                raise MisconfigurationException(
                    "The lr scheduler dict must include a monitor when a `ReduceLROnPlateau` scheduler is used."
                    ' For example: {"optimizer": optimizer, "lr_scheduler":'
                    ' {"scheduler": scheduler, "monitor": "your_loss"}}'
                )
            is_one_cycle = isinstance(scheduler["scheduler"], optim.lr_scheduler.OneCycleLR)
            if is_one_cycle and scheduler.get("interval", "epoch") == "epoch":

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Use the key 'scheduler': {'optimizer': opt, 'lr_scheduler': {'scheduler': sched, 'monitor': 'val_loss'}}
  2. Or simply return the bare scheduler object and let Lightning wrap it: return opt, sched

Example fix

# before
return {'optimizer': opt, 'lr_scheduler': {'lr_scheduler': sched, 'monitor': 'val_loss'}}
# after
return {'optimizer': opt, 'lr_scheduler': {'scheduler': sched, 'monitor': 'val_loss'}}
Defensive patterns

Strategy: validation

Validate before calling

for s in schedulers:
    if isinstance(s, dict):
        assert "scheduler" in s, 'scheduler dict needs key "scheduler"'

Type guard

def is_valid_sched_dict(d: dict) -> bool:
    return isinstance(d, dict) and "scheduler" in d

Prevention

When it happens

Trigger: Returning {'lr_scheduler': sched, 'monitor': 'val_loss'} — nesting under 'lr_scheduler' instead of using the key 'scheduler' inside the scheduler dict.

Common situations: Confusion between the top-level configure_optimizers dict (key 'lr_scheduler') and the per-scheduler dict (key 'scheduler'); renaming or hand-writing the dict and omitting the key.

Related errors


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