Lightning-AI/pytorch-lightning · error · ValueError
`ModelCheckpoint(save_last='link')` is only supported for lo
Error message
`ModelCheckpoint(save_last='link')` is only supported for local file paths, got `dirpath={dirpath}`. What it means
ModelCheckpoint's `save_last='link'` creates a filesystem symlink ('last.ckpt' -> best checkpoint), which only works on local paths. In `setup()`, if `save_last == 'link'` and the dirpath scheme isn't a local file protocol (e.g. s3://, gs://), a ValueError is raised.
Source
Thrown at src/lightning/pytorch/callbacks/model_checkpoint.py:331
def state_key(self) -> str:
return self._generate_state_key(
monitor=self.monitor,
mode=self.mode,
every_n_train_steps=self._every_n_train_steps,
every_n_epochs=self._every_n_epochs,
train_time_interval=self._train_time_interval,
)
@override
def setup(self, trainer: "pl.Trainer", pl_module: "pl.LightningModule", stage: str) -> None:
dirpath = self.__resolve_ckpt_dir(trainer)
dirpath = trainer.strategy.broadcast(dirpath)
self.dirpath = dirpath
self._fs = get_filesystem(self.dirpath or "")
if trainer.is_global_zero and stage == "fit":
self.__warn_if_dir_not_empty(self.dirpath)
if self.save_last == "link" and not _is_local_file_protocol(self.dirpath):
raise ValueError(
f"`ModelCheckpoint(save_last='link')` is only supported for local file paths, got `dirpath={dirpath}`."
)
@override
def on_train_start(self, trainer: "pl.Trainer", pl_module: "pl.LightningModule") -> None:
self._last_time_checked = time.monotonic()
@override
def on_train_batch_end(
self,
trainer: "pl.Trainer",
pl_module: "pl.LightningModule",
outputs: STEP_OUTPUT,
batch: Any,
batch_idx: int,
) -> None:
"""Save checkpoint on train batch end if we meet the criteria for `every_n_train_steps`"""
# For manual optimization, we need to handle saving differentlyView on GitHub (pinned to 9fed5c27d2)
Solutions
- Use `save_last=True` instead of 'link' for remote paths (copies rather than symlinks)
- Or keep dirpath local (e.g. './checkpoints') and sync to remote separately
- Or use 'link' only where the filesystem supports symlinks
Example fix
# before ModelCheckpoint(dirpath='s3://my-bucket/run1', save_last='link') # after ModelCheckpoint(dirpath='s3://my-bucket/run1', save_last=True)
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
scheme = urlparse(dirpath or '').scheme
if save_last == 'link' and scheme not in ('', 'file'):
save_last = True # fall back to copy for remote storage Type guard
def link_save_last_ok(dirpath: str) -> bool:
from urllib.parse import urlparse
return urlparse(dirpath or '').scheme in ('', 'file') Prevention
- Default to save_last=True; only use 'link' when dirpath is local
- Sync local checkpoints to remote storage as a separate step
When it happens
Trigger: `ModelCheckpoint(dirpath='s3://bucket/ckpt', save_last='link')` or letting default dirpath resolve to a remote fsspec URL, then starting a fit. Only the 'link' mode is restricted; `save_last=True` (copy) works remotely.
Common situations: Cloud storage checkpoints on S3/GCS/Azure; Lightning's default remote checkpointing in cluster setups; switching a working local config to a remote dirpath without changing save_last.
Related errors
- `ModelCheckpoint(monitor={self.monitor!r})` could not find t
- Invalid value for save_top_k={self.save_top_k}. Must be >= -
- `.{fn}(ckpt_path="best")` is set but `ModelCheckpoint` is no
- The dirpath has changed from {dirpath_from_ckpt!r} to {self.
- Received multiple values for {', '.join(duplicated_plugin_ke
AI-assisted analysis of Lightning-AI/pytorch-lightning@9fed5c27d2 (2026-08-28).
Data as JSON: /api/errors/c1d167695ebee4a0.
Report an issue: GitHub.