{"record":{"id":"b9e9bec3089fbbba","repo":"Lightning-AI/pytorch-lightning","slug":"the-lr-scheduler-dict-must-have-the-key-scheduler","errorCode":null,"errorMessage":"The lr scheduler dict must have the key \"scheduler\" with its item being an lr scheduler","messagePattern":"The lr scheduler dict must have the key \"scheduler\" with its item being an lr scheduler","errorType":"exception","errorClass":"MisconfigurationException","httpStatus":null,"severity":"critical","filePath":"src/lightning/pytorch/core/optimizer.py","lineNumber":266,"sourceCode":"\n\ndef _configure_schedulers_automatic_opt(schedulers: list, monitor: Optional[str]) -> list[LRSchedulerConfig]:\n    \"\"\"Convert each scheduler into `LRSchedulerConfig` with relevant information, when using automatic optimization.\"\"\"\n    lr_scheduler_configs = []\n    for scheduler in schedulers:\n        if isinstance(scheduler, dict):\n            # check provided keys\n            supported_keys = {field.name for field in fields(LRSchedulerConfig)}\n            extra_keys = scheduler.keys() - supported_keys\n            if extra_keys:\n                rank_zero_warn(\n                    f\"Found unsupported keys in the lr scheduler dict: {extra_keys}.\"\n                    \" HINT: remove them from the output of `configure_optimizers`.\",\n                    category=RuntimeWarning,\n                )\n                scheduler = {k: v for k, v in scheduler.items() if k in supported_keys}\n            if \"scheduler\" not in scheduler:\n                raise MisconfigurationException(\n                    'The lr scheduler dict must have the key \"scheduler\" with its item being an lr scheduler'\n                )\n            if \"interval\" in scheduler and scheduler[\"interval\"] not in (\"step\", \"epoch\"):\n                raise MisconfigurationException(\n                    'The \"interval\" key in lr scheduler dict must be \"step\" or \"epoch\"'\n                    f' but is \"{scheduler[\"interval\"]}\"'\n                )\n            scheduler[\"reduce_on_plateau\"] = scheduler.get(\n                \"reduce_on_plateau\", isinstance(scheduler[\"scheduler\"], optim.lr_scheduler.ReduceLROnPlateau)\n            )\n            if scheduler[\"reduce_on_plateau\"] and scheduler.get(\"monitor\") is None:\n                raise MisconfigurationException(\n                    \"The lr scheduler dict must include a monitor when a `ReduceLROnPlateau` scheduler is used.\"\n                    ' For example: {\"optimizer\": optimizer, \"lr_scheduler\":'\n                    ' {\"scheduler\": scheduler, \"monitor\": \"your_loss\"}}'\n                )\n            is_one_cycle = isinstance(scheduler[\"scheduler\"], optim.lr_scheduler.OneCycleLR)\n            if is_one_cycle and scheduler.get(\"interval\", \"epoch\") == \"epoch\":","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/pytorch/core/optimizer.py#L248-L284","documentation":"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.","triggerScenarios":"Returning {'lr_scheduler': sched, 'monitor': 'val_loss'} — nesting under 'lr_scheduler' instead of using the key 'scheduler' inside the scheduler dict.","commonSituations":"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.","solutions":["Use the key 'scheduler': {'optimizer': opt, 'lr_scheduler': {'scheduler': sched, 'monitor': 'val_loss'}}","Or simply return the bare scheduler object and let Lightning wrap it: return opt, sched"],"exampleFix":"# before\nreturn {'optimizer': opt, 'lr_scheduler': {'lr_scheduler': sched, 'monitor': 'val_loss'}}\n# after\nreturn {'optimizer': opt, 'lr_scheduler': {'scheduler': sched, 'monitor': 'val_loss'}}","handlingStrategy":"validation","validationCode":"for s in schedulers:\n    if isinstance(s, dict):\n        assert \"scheduler\" in s, 'scheduler dict needs key \"scheduler\"'","typeGuard":"def is_valid_sched_dict(d: dict) -> bool:\n    return isinstance(d, dict) and \"scheduler\" in d","tryCatchPattern":null,"preventionTips":["Return bare scheduler objects where possible so Lightning builds the dict","Keep scheduler dict construction in one helper to avoid key typos"],"tags":["lr-scheduler","configure-optimizers","validation","lightning"],"backgroundTag":"invalid-configuration-shape","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}