Lightning-AI/pytorch-lightning · error · IsADirectoryError

The checkpoint path exists and is a directory: {path}

Error message

The checkpoint path exists and is a directory: {path}

What it means

With state_dict_type="full", FSDP saves a single consolidated file and expects `filepath` to be a file path. If the broadcast path resolves to an existing directory that is not a sharded checkpoint (no sharded metadata), save_checkpoint raises IsADirectoryError to avoid writing a file over a checkpoint directory.

Source

Thrown at src/lightning/pytorch/strategies/fsdp.py:577

    @override
    def load_optimizer_state_dict(self, checkpoint: Mapping[str, Any]) -> None:
        # Override to do nothing, the FSDP already loaded the states in `load_checkpoint()`
        pass

    @override
    def save_checkpoint(
        self, checkpoint: dict[str, Any], filepath: _PATH, storage_options: Optional[Any] = None
    ) -> None:
        if storage_options is not None:
            raise TypeError(
                "`FSDPStrategy.save_checkpoint(..., storage_options=...)` is not supported because"
                " `FSDPStrategy` does not use the `CheckpointIO`."
            )

        path = _resolve_path(self.broadcast(filepath))
        if self._state_dict_type == "full" and _is_checkpoint_dir(path) and not _is_sharded_checkpoint(path):
            raise IsADirectoryError(f"The checkpoint path exists and is a directory: {path}")

        if self._state_dict_type == "sharded":
            _prepare_directory_checkpoint(path)

            converted_state = {"model": checkpoint.pop("state_dict")}
            converted_state.update({
                f"optimizer_{idx}": optim_state
                for idx, optim_state in enumerate(checkpoint.pop("optimizer_states", []))
            })

            _distributed_checkpoint_save(converted_state, path)

            if self.global_rank == 0:
                _atomic_save(checkpoint, _checkpoint_join(path, _METADATA_FILENAME))
        elif self._state_dict_type == "full":
            if _is_sharded_checkpoint(path):
                _remove_checkpoint(path)
            return super().save_checkpoint(checkpoint=checkpoint, filepath=path)

View on GitHub (pinned to 9fed5c27d2)

Solutions

  1. Point save_checkpoint at a file path such as `.../last.ckpt` that does not exist as a directory
  2. Delete or move the existing directory before saving
  3. Keep sharded and full checkpoint outputs in separate paths

Example fix

# before
trainer.save_checkpoint("checkpoints/run1")  # existing dir

# after
trainer.save_checkpoint("checkpoints/run1/last.ckpt")
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
path = Path("checkpoints/run1/last.ckpt")
if path.is_dir():
    raise IsADirectoryError(f"pick a file path, got dir: {path}")
trainer.save_checkpoint(str(path))

Prevention

When it happens

Trigger: `FSDPStrategy(state_dict_type="full")` + `trainer.save_checkpoint(path)` where path exists on disk as a directory (e.g. a previous sharded checkpoint dir or a logs dir).

Common situations: Reusing the same checkpoint path for a full save after earlier sharded saves; pointing save path at a run directory like `logs/run1/`; callbacks deriving paths from existing dirs.

Related errors


AI-assisted analysis of Lightning-AI/pytorch-lightning@9fed5c27d2 (2026-08-28). Data as JSON: /api/errors/9c22c46340d68730. Report an issue: GitHub.