Lightning-AI/pytorch-lightning · error · MisconfigurationException

ReduceLROnPlateau conditioned on metric {monitor_key} which

Error message

ReduceLROnPlateau conditioned on metric {monitor_key} which is not available. Available metrics are: {avail_metrics}. Condition can be set using `monitor` key in lr scheduler dict

What it means

Raised in _update_learning_rates when a ReduceLROnPlateau scheduler is configured (strict=True by default) with a `monitor` metric that is absent from trainer.callback_metrics at epoch end. ReduceLROnPlateau needs the monitored value each epoch to decide whether to reduce LR; without it the scheduler cannot operate.

Source

Thrown at src/lightning/pytorch/loops/training_epoch_loop.py:495

        for config in trainer.lr_scheduler_configs:
            if update_plateau_schedulers ^ config.reduce_on_plateau:
                continue

            current_idx = self.batch_idx if interval == "step" else trainer.current_epoch
            current_idx += 1  # account for both batch and epoch starts from 0
            # Take step if call to update_learning_rates matches the interval key and
            # the current step modulo the schedulers frequency is zero
            if config.interval == interval and current_idx % config.frequency == 0:
                monitor_val = None
                if config.reduce_on_plateau:
                    monitor_key = config.monitor
                    assert monitor_key is not None
                    monitor_val = self._get_monitor_value(monitor_key)
                    if monitor_val is None:
                        if config.strict:
                            avail_metrics = list(trainer.callback_metrics)
                            raise MisconfigurationException(
                                f"ReduceLROnPlateau conditioned on metric {monitor_key}"
                                f" which is not available. Available metrics are: {avail_metrics}."
                                " Condition can be set using `monitor` key in lr scheduler dict"
                            )
                        rank_zero_warn(
                            f"ReduceLROnPlateau conditioned on metric {monitor_key}"
                            " which is not available but strict is set to `False`."
                            " Skipping learning rate update.",
                            category=RuntimeWarning,
                        )
                        continue

                self.scheduler_progress.increment_ready()

                # update LR
                call._call_lightning_module_hook(
                    trainer,
                    "lr_scheduler_step",

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Log the monitored metric: `self.log('val_loss', loss, prog_bar=True)` (ensure it lands in callback_metrics, i.e. epoch-level aggregation)
  2. Fix the monitor string to exactly match the logged metric name
  3. If absence is acceptable, set `strict=False` in the scheduler dict to downgrade to a warning

Example fix

# before
# in configure_optimizers
return {'optimizer': opt, 'scheduler': ReduceLROnPlateau(opt), 'monitor': 'val_f1'}
# validation_step only logs 'val_loss'

# after
def validation_step(self, batch, batch_idx):
    loss, f1 = self._step(batch)
    self.log('val_f1', f1, on_epoch=True, prog_bar=True)
    return loss
Defensive patterns

Strategy: validation

Validate before calling

# in configure_optimizers or LightningModule setup
monitor = 'val_loss'
logged = {'val_loss'}  # metrics you reliably self.log() with on_epoch aggregation
assert monitor in logged or not strict, f'{monitor} not logged'

Type guard

def monitor_available(monitor: str, model) -> bool:
    return monitor in model.trainer.callback_metrics if model.trainer else monitor in model._logged_metric_names

Try / catch

try:
    trainer.fit(model, datamodule=dm)
except MisconfigurationException as e:
    if 'ReduceLROnPlateau' in str(e):
        raise ValueError(f"monitor metric missing: verify self.log('{monitor}', ...) exists") from e
    raise

Prevention

When it happens

Trigger: `configure_optimizers` returning `{'scheduler': torch.optim.lr_scheduler.ReduceLROnPlateau(opt), 'monitor': 'val_loss'}` while `validation_step`/`training_step` never calls `self.log('val_loss', ...)`; monitor name typo like 'val/loss' vs 'val_loss'; metric logged only under a condition that skips.

Common situations: Renaming logged metrics without updating the scheduler dict; running with limit_val_batches=0 so the val metric is never produced; early in training when the metric is logged with on_epoch=False only.

Related errors


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