{"record":{"id":"00929788bf512d42","repo":"Lightning-AI/pytorch-lightning","slug":"mode-can-be-join-mode-dict-keys-but-go","errorCode":null,"errorMessage":"`mode` can be {', '.join(mode_dict.keys())} but got {mode}","messagePattern":"`mode` can be (.+?) but got (.+?)","errorType":"exception","errorClass":"MisconfigurationException","httpStatus":null,"severity":"error","filePath":"src/lightning/pytorch/callbacks/model_checkpoint.py","lineNumber":707,"sourceCode":"                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:\n            raise MisconfigurationException(f\"`mode` can be {', '.join(mode_dict.keys())} but got {mode}\")\n\n        self.kth_value, self.mode = mode_dict[mode]\n\n    def __init_triggers(\n        self,\n        every_n_train_steps: Optional[int],\n        every_n_epochs: Optional[int],\n        train_time_interval: Optional[timedelta],\n    ) -> None:\n        # Default to running once after each validation epoch if neither\n        # every_n_train_steps nor every_n_epochs is set\n        if every_n_train_steps is None and every_n_epochs is None and train_time_interval is None:\n            every_n_epochs = 1\n            every_n_train_steps = 0\n            log.debug(\"Both every_n_train_steps and every_n_epochs are not set. Setting every_n_epochs=1\")\n        else:\n            every_n_epochs = every_n_epochs or 0\n            every_n_train_steps = every_n_train_steps or 0","sourceCodeStart":689,"sourceCodeEnd":725,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/pytorch/callbacks/model_checkpoint.py#L689-L725","documentation":"ModelCheckpoint's mode decides whether 'best' means lowest ('min') or highest ('max') value of the monitored quantity. __init_monitor_mode accepts only the strings 'min' or 'max'; anything else raises MisconfigurationException before training starts.","triggerScenarios":"Passing mode='minimum', mode='maximize', mode='Max', mode='asc'/'desc', or a typo like 'minn' to ModelCheckpoint; building the string dynamically from a config with unexpected casing.","commonSituations":"Configs written for other frameworks (e.g., mlflow or sklearn use different terminology); case sensitivity surprises ('Min' fails); typos in YAML files.","solutions":["Use exactly mode='min' (loss, error) or mode='max' (accuracy, F1)","If the value comes from config, normalize it: mode=str(mode).lower() and validate against ('min','max')","Add a startup assert for config-sourced mode strings"],"exampleFix":"# before\nModelCheckpoint(monitor='val_acc', mode='maximize')\n# after\nModelCheckpoint(monitor='val_acc', mode='max')","handlingStrategy":"validation","validationCode":"mode = str(cfg['mode']).lower()\nassert mode in ('min', 'max'), f\"mode must be 'min' or 'max', got {mode!r}\"","typeGuard":"def is_valid_mode(m: str) -> bool:\n    return isinstance(m, str) and m.lower() in ('min', 'max')","tryCatchPattern":null,"preventionTips":["Normalize casing from configs before passing","Use mode='min' for losses, 'max' for accuracies"],"tags":["pytorch-lightning","modelcheckpoint","mode","argument-validation"],"backgroundTag":"invalid-enum-value","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}