Lightning-AI/pytorch-lightning · critical · MisconfigurationException

Some schedulers are attached with an optimizer that wasn't r

Error message

Some schedulers are attached with an optimizer that wasn't returned from `configure_optimizers`.

What it means

Every LRScheduler is bound to a specific optimizer (scheduler.optimizer). During setup Lightning verifies each scheduler's optimizer is among those returned from configure_optimizers; a scheduler attached to a foreign optimizer raises MisconfigurationException.

Source

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

def _validate_multiple_optimizers_support(optimizers: list[Optimizer], model: "pl.LightningModule") -> None:
    if is_param_in_hook_signature(model.training_step, "optimizer_idx", explicit=True):
        raise RuntimeError(
            "Training with multiple optimizers is only supported with manual optimization. Remove the `optimizer_idx`"
            " argument from `training_step`, set `self.automatic_optimization = False` and access your optimizers"
            " in `training_step` with `opt1, opt2, ... = self.optimizers()`."
        )
    if model.automatic_optimization and len(optimizers) > 1:
        raise RuntimeError(
            "Training with multiple optimizers is only supported with manual optimization. Set"
            " `self.automatic_optimization = False`, then access your optimizers in `training_step` with"
            " `opt1, opt2, ... = self.optimizers()`."
        )


def _validate_optimizers_attached(optimizers: list[Optimizer], lr_scheduler_configs: list[LRSchedulerConfig]) -> None:
    for config in lr_scheduler_configs:
        if config.scheduler.optimizer not in optimizers:
            raise MisconfigurationException(
                "Some schedulers are attached with an optimizer that wasn't returned from `configure_optimizers`."
            )


def _validate_optim_conf(optim_conf: dict[str, Any]) -> None:
    valid_keys = {"optimizer", "lr_scheduler", "monitor"}
    extra_keys = optim_conf.keys() - valid_keys
    if extra_keys:
        rank_zero_warn(
            f"Found unsupported keys in the optimizer configuration: {set(extra_keys)}", category=RuntimeWarning
        )


class _MockOptimizer(Optimizer):
    """The `_MockOptimizer` will be used inplace of an optimizer in the event that `None` is returned from
    :meth:`~lightning.pytorch.core.LightningModule.configure_optimizers`."""

    def __init__(self) -> None:

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Create the scheduler from the exact optimizer object you return: opt = Adam(...); sched = StepLR(opt, 1); return [opt], [sched]
  2. Avoid re-instantiating optimizers between configure_optimizers calls; reuse self parameters and the same objects
  3. When exchanging schedulers/optimizers programmatically, rebuild the scheduler against the new optimizer

Example fix

# before
def configure_optimizers(self):
    sched = StepLR(Adam(self.parameters()), 1)  # hidden optimizer
    return [Adam(self.parameters())], [sched]  # different instance
# after
def configure_optimizers(self):
    opt = Adam(self.parameters())
    return [opt], [StepLR(opt, 1)]
Defensive patterns

Strategy: validation

Validate before calling

returned = set(map(id, optimizers))
for cfg in sched_configs:
    assert id(cfg.scheduler.optimizer) in returned, "scheduler bound to foreign optimizer"

Type guard

def schedulers_attached(schedulers, optimizers) -> bool:
    opt_ids = {id(o) for o in optimizers}
    return all(id(s.optimizer) in opt_ids for s in schedulers)

Prevention

When it happens

Trigger: Constructing schedulers over an optimizer that is not returned: sched = StepLR(torch.optim.Adam(model.parameters()), ...) while configure_optimizers returns a different Adam instance; also common when re-running setup after _exchange_scheduler swaps schedulers.

Common situations: Creating optimizer/scheduler pairs with helper functions that instantiate fresh optimizers, or swapping optimizer state in before_configure or on resume so scheduler.optimizer no longer matches the returned list.

Related errors


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