{"record":{"id":"54ef4a10d0d09ac7","repo":"Lightning-AI/pytorch-lightning","slug":"the-dirpath-has-changed-from-dirpath-from-ckpt-r","errorCode":null,"errorMessage":"The dirpath has changed from {dirpath_from_ckpt!r} to {self.dirpath!r}, therefore `best_model_score`, `kth_best_model_path`, `kth_value`, `last_model_path` and `best_k_models` won't be reloaded. Only `best_model_path` will be reloaded.","messagePattern":"The dirpath has changed from (.+?) to (.+?), therefore `best_model_score`, `kth_best_model_path`, `kth_value`, `last_model_path` and `best_k_models` won't be reloaded\\. Only `best_model_path` will be reloaded\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lightning/pytorch/callbacks/model_checkpoint.py","lineNumber":566,"sourceCode":"            \"dirpath\": self.dirpath,\n            \"best_k_models\": self.best_k_models,\n            \"kth_best_model_path\": self.kth_best_model_path,\n            \"kth_value\": self.kth_value,\n            \"last_model_path\": self.last_model_path,\n        }\n\n    @override\n    def load_state_dict(self, state_dict: dict[str, Any]) -> None:\n        dirpath_from_ckpt = state_dict.get(\"dirpath\", self.dirpath)\n\n        if self.dirpath == dirpath_from_ckpt:\n            self.best_model_score = state_dict[\"best_model_score\"]\n            self.kth_best_model_path = state_dict.get(\"kth_best_model_path\", self.kth_best_model_path)\n            self.kth_value = state_dict.get(\"kth_value\", self.kth_value)\n            self.best_k_models = state_dict.get(\"best_k_models\", self.best_k_models)\n            self.last_model_path = state_dict.get(\"last_model_path\", self.last_model_path)\n        else:\n            warnings.warn(\n                f\"The dirpath has changed from {dirpath_from_ckpt!r} to {self.dirpath!r},\"\n                \" therefore `best_model_score`, `kth_best_model_path`, `kth_value`, `last_model_path` and\"\n                \" `best_k_models` won't be reloaded. Only `best_model_path` will be reloaded.\"\n            )\n\n        self.best_model_path = state_dict[\"best_model_path\"]\n\n    def _save_topk_checkpoint(self, trainer: \"pl.Trainer\", monitor_candidates: dict[str, Tensor]) -> None:\n        if self.save_top_k == 0:\n            return\n\n        # validate metric\n        if self.monitor is not None:\n            if self.monitor not in monitor_candidates:\n                m = (\n                    f\"`ModelCheckpoint(monitor={self.monitor!r})` could not find the monitored key in the returned\"\n                    f\" metrics: {list(monitor_candidates)}.\"\n                    f\" HINT: Did you call `log({self.monitor!r}, value)` in the `LightningModule`?\"","sourceCodeStart":548,"sourceCodeEnd":584,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/pytorch/callbacks/model_checkpoint.py#L548-L584","documentation":"When ModelCheckpoint.load_state_dict restores from a checkpoint whose dirpath differs from the current callback's dirpath, only best_model_path is restored; the other state (best_model_score, kth_best_model_path, kth_value, last_model_path, best_k_models) is dropped because those files live in the old directory.","triggerScenarios":"Resuming training with Trainer(plugins=[ModelCheckpoint(dirpath='new/dir')], ...) from a ckpt_path saved with a different dirpath (or after changing default_root_dir/CV options).","commonSituations":"Changing output directories between runs, resume scripts with timestamped dirpaths, hyperparameter sweeps reusing callbacks.","solutions":["Keep the same dirpath when resuming: reuse the ModelCheckpoint config from the original run","Or read the old checkpoint's callback_state and manually restore best_model_score etc.","Or treat resume as a fresh checkpoint lineage and accept the reset"],"exampleFix":"# before\nckpt = ModelCheckpoint(dirpath=f'runs/{timestamp}')  # changes every run\ntrainer.fit(model, ckpt_path='runs/old/last.ckpt', callbacks=[ckpt])\n# after\nckpt = ModelCheckpoint(dirpath='runs/exp1')\ntrainer.fit(model, ckpt_path='runs/exp1/last.ckpt', callbacks=[ckpt])","handlingStrategy":"validation","validationCode":"import torch\nckpt = torch.load(ckpt_path, map_location='cpu', weights_only=False)\nstate = next(c for c in ckpt['callbacks'] if 'ModelCheckpoint' in c)\nassert state.get('dirpath') == mc.dirpath, 'dirpath changed; state will not fully restore'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use stable, deterministic dirpaths per experiment","Recreate identical ModelCheckpoint configs when resuming"],"tags":["model-checkpoint","resume","dirpath","lightning"],"backgroundTag":"checkpoint-state-mismatch","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}