Lightning-AI/pytorch-lightning · error · MisconfigurationException
ModelCheckpoint(save_top_k={self.save_top_k}, monitor=None)
Error message
ModelCheckpoint(save_top_k={self.save_top_k}, monitor=None) is not a valid configuration. No quantity for top_k to track. What it means
save_top_k determines how many 'best' checkpoints to keep by ranking a monitored quantity. Without a monitor, there is no quantity to rank, so only save_top_k in (-1, 0, 1) is meaningful: -1 saves everything, 0 saves nothing, 1 keeps the latest. Any other value with monitor=None is rejected at __init__.
Source
Thrown at src/lightning/pytorch/callbacks/model_checkpoint.py:688
raise MisconfigurationException(
f"Invalid value for every_n_train_steps={self._every_n_train_steps}. Must be >= 0"
)
if self._every_n_epochs < 0:
raise MisconfigurationException(f"Invalid value for every_n_epochs={self._every_n_epochs}. Must be >= 0")
every_n_train_steps_triggered = self._every_n_train_steps >= 1
every_n_epochs_triggered = self._every_n_epochs >= 1
train_time_interval_triggered = self._train_time_interval is not None
if every_n_train_steps_triggered + every_n_epochs_triggered + train_time_interval_triggered > 1:
raise MisconfigurationException(
f"Combination of parameters every_n_train_steps={self._every_n_train_steps}, "
f"every_n_epochs={self._every_n_epochs} and train_time_interval={self._train_time_interval} "
"should be mutually exclusive."
)
if self.monitor is None and self.save_top_k not in (-1, 0, 1):
# -1: save all epochs, 0: nothing is saved, 1: save last epoch
raise MisconfigurationException(
f"ModelCheckpoint(save_top_k={self.save_top_k}, monitor=None) is not a valid"
" configuration. No quantity for top_k to track."
)
def __init_ckpt_dir(self, dirpath: Optional[_PATH], filename: Optional[str]) -> None:
self._fs = get_filesystem(dirpath if dirpath else "")
if dirpath and _is_local_file_protocol(dirpath if dirpath else ""):
dirpath = os.path.realpath(os.path.expanduser(dirpath))
self.dirpath = dirpath
self.filename = filename
def __init_monitor_mode(self, mode: str) -> None:
torch_inf = torch.tensor(torch.inf)
mode_dict = {"min": (torch_inf, "min"), "max": (-torch_inf, "max")}
if mode not in mode_dict:View on GitHub (pinned to 9fed5c27d2)
Solutions
- Set monitor to a metric your model logs (e.g., monitor='val_loss', mode='min') so save_top_k>1 has something to rank
- Or use save_top_k=1 to keep only the latest checkpoint when no metric is tracked
- Ensure the monitored metric is actually logged via self.log in validation/test steps
Example fix
# before ModelCheckpoint(save_top_k=3) # after ModelCheckpoint(monitor='val_loss', mode='min', save_top_k=3)
Defensive patterns
Strategy: validation
Validate before calling
if ckpt_cfg.get('save_top_k', 1) not in (-1, 0, 1):
assert ckpt_cfg.get('monitor'), 'save_top_k > 1 requires a monitor metric' Type guard
def ckpt_config_valid(c: dict) -> bool:
return c.get('save_top_k', 1) in (-1, 0, 1) or bool(c.get('monitor')) Prevention
- Always pair save_top_k>1 with an explicit monitor and mode
- Ensure the monitored metric is logged via self.log
When it happens
Trigger: ModelCheckpoint(save_top_k=3) (or any value besides -1/0/1) without setting monitor; passing save_top_k from a config while forgetting the monitor key; setting save_top_k before deciding what metric to track.
Common situations: Default configs that assume a monitor (e.g., 'val_loss') exists but the model doesn't log it or monitor wasn't specified; transferring a Keras-style 'keep best 3' mental model without naming a metric.
Related errors
- Invalid value for every_n_train_steps={self._every_n_train_s
- Invalid value for every_n_epochs={self._every_n_epochs}. Mus
- Combination of parameters every_n_train_steps={self._every_n
- `precision={precision!r})` is not supported in DeepSpeed. `p
- `precision={precision!r})` is not supported in FSDP. `precis
AI-assisted analysis of Lightning-AI/pytorch-lightning@9fed5c27d2 (2026-08-28).
Data as JSON: /api/errors/2d2f39ab6fc4887c.
Report an issue: GitHub.