{"record":{"id":"2d2f39ab6fc4887c","repo":"Lightning-AI/pytorch-lightning","slug":"modelcheckpoint-save-top-k-self-save-top-k-moni","errorCode":null,"errorMessage":"ModelCheckpoint(save_top_k={self.save_top_k}, monitor=None) is not a valid configuration. No quantity for top_k to track.","messagePattern":"ModelCheckpoint\\(save_top_k=(.+?), monitor=None\\) is not a valid configuration\\. No quantity for top_k to track\\.","errorType":"validation","errorClass":"MisconfigurationException","httpStatus":null,"severity":"error","filePath":"src/lightning/pytorch/callbacks/model_checkpoint.py","lineNumber":688,"sourceCode":"            raise MisconfigurationException(\n                f\"Invalid value for every_n_train_steps={self._every_n_train_steps}. Must be >= 0\"\n            )\n        if self._every_n_epochs < 0:\n            raise MisconfigurationException(f\"Invalid value for every_n_epochs={self._every_n_epochs}. Must be >= 0\")\n\n        every_n_train_steps_triggered = self._every_n_train_steps >= 1\n        every_n_epochs_triggered = self._every_n_epochs >= 1\n        train_time_interval_triggered = self._train_time_interval is not None\n        if every_n_train_steps_triggered + every_n_epochs_triggered + train_time_interval_triggered > 1:\n            raise MisconfigurationException(\n                f\"Combination of parameters every_n_train_steps={self._every_n_train_steps}, \"\n                f\"every_n_epochs={self._every_n_epochs} and train_time_interval={self._train_time_interval} \"\n                \"should be mutually exclusive.\"\n            )\n\n        if self.monitor is None and self.save_top_k not in (-1, 0, 1):\n            # -1: save all epochs, 0: nothing is saved, 1: save last epoch\n            raise MisconfigurationException(\n                f\"ModelCheckpoint(save_top_k={self.save_top_k}, monitor=None) is not a valid\"\n                \" configuration. No quantity for top_k to track.\"\n            )\n\n    def __init_ckpt_dir(self, dirpath: Optional[_PATH], filename: Optional[str]) -> None:\n        self._fs = get_filesystem(dirpath if dirpath else \"\")\n\n        if dirpath and _is_local_file_protocol(dirpath if dirpath else \"\"):\n            dirpath = os.path.realpath(os.path.expanduser(dirpath))\n\n        self.dirpath = dirpath\n        self.filename = filename\n\n    def __init_monitor_mode(self, mode: str) -> None:\n        torch_inf = torch.tensor(torch.inf)\n        mode_dict = {\"min\": (torch_inf, \"min\"), \"max\": (-torch_inf, \"max\")}\n\n        if mode not in mode_dict:","sourceCodeStart":670,"sourceCodeEnd":706,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/pytorch/callbacks/model_checkpoint.py#L670-L706","documentation":"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__.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nModelCheckpoint(save_top_k=3)\n# after\nModelCheckpoint(monitor='val_loss', mode='min', save_top_k=3)","handlingStrategy":"validation","validationCode":"if ckpt_cfg.get('save_top_k', 1) not in (-1, 0, 1):\n    assert ckpt_cfg.get('monitor'), 'save_top_k > 1 requires a monitor metric'","typeGuard":"def ckpt_config_valid(c: dict) -> bool:\n    return c.get('save_top_k', 1) in (-1, 0, 1) or bool(c.get('monitor'))","tryCatchPattern":null,"preventionTips":["Always pair save_top_k>1 with an explicit monitor and mode","Ensure the monitored metric is logged via self.log"],"tags":["pytorch-lightning","modelcheckpoint","monitor","config-validation"],"backgroundTag":"missing-monitor-metric","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}