apache/seatunnel · error · CheckpointStorageException

${ExceptionUtils.getMessage(e)}

Error message

${ExceptionUtils.getMessage(e)}

What it means

LocalFileStorage.getLatestCheckpoint throws CheckpointStorageException with the flattened message of the underlying exception when listing checkpoint files in the job directory fails with anything other than a NoSuchFileException cause. A missing directory is tolerated (returns empty list), but genuine IO failures (permissions, disk errors) are surfaced. The message is the ExceptionUtils.getMessage of the original exception, so the root cause text is embedded.

Source

Thrown at seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-local-file/src/main/java/org/apache/seatunnel/engine/checkpoint/storage/localfile/LocalFileStorage.java:157

                    } catch (IOException e) {
                        log.error(
                                "Failed to read checkpoint data from file "
                                        + file.getAbsolutePath(),
                                e);
                    }
                });
        return states;
    }

    @Override
    public List<PipelineState> getLatestCheckpoint(String jobId) throws CheckpointStorageException {
        String parentPath = getStorageParentDirectory() + jobId;
        Collection<File> fileList = new ArrayList<>();
        try {
            fileList = FileUtils.listFiles(new File(parentPath), FILE_EXTENSIONS, false);
        } catch (Exception e) {
            if (!(e.getCause() instanceof NoSuchFileException)) {
                throw new CheckpointStorageException(ExceptionUtils.getMessage(e));
            }
        }
        if (fileList.isEmpty()) {
            log.info("No checkpoint found for this  job, the job id is: " + jobId);
            return new ArrayList<>();
        }
        Map<String, File> fileMap =
                fileList.stream()
                        .collect(
                                Collectors.toMap(
                                        File::getName, Function.identity(), (v1, v2) -> v2));
        Set<String> latestPipelines = getLatestPipelineNames(fileMap.keySet());
        List<PipelineState> latestPipelineFiles = new ArrayList<>(latestPipelines.size());
        latestPipelines.forEach(
                fileName -> {
                    File file = fileMap.get(fileName);
                    try {
                        byte[] data = FileUtils.readFileToByteArray(file);

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Inspect the embedded cause message to identify the filesystem failure (permission, IO, etc.).
  2. Fix directory permissions so the engine user can read the job's checkpoint directory.
  3. Verify the storage parent directory config resolves to a valid mounted path.
  4. If the directory may legitimately be absent, ensure cleanup logic deletes the whole directory (then a NoSuchFileException is tolerated and an empty list is returned).

Example fix

// before
throw new CheckpointStorageException(ExceptionUtils.getMessage(e));
// after
throw new CheckpointStorageException(
    "Failed to list checkpoints for job " + jobId + ": " + ExceptionUtils.getMessage(e), e);
Defensive patterns

Strategy: try-catch

Validate before calling

java.nio.file.Path dir = java.nio.file.Path.of(storageParentDir, jobId);
if (java.nio.file.Files.exists(dir) && !(java.nio.file.Files.isDirectory(dir) && java.nio.file.Files.isReadable(dir))) {
    throw new IllegalStateException("Checkpoint path exists but is not a readable directory: " + dir);
}

Type guard

static boolean listableDirectory(Path p) {
    return !Files.exists(p) || (Files.isDirectory(p) && Files.isReadable(p));
}

Try / catch

try {
    latest = storage.getLatestCheckpoint(jobId);
} catch (CheckpointStorageException e) {
    log.error("Listing checkpoints failed for job {}: {}", jobId, e.getMessage(), e);
    latest = Collections.emptyList(); // or rethrow depending on recovery policy
}

Prevention

When it happens

Trigger: Calling getLatestCheckpoint(jobId) when FileUtils.listFiles on getStorageParentDirectory()+jobId throws an exception whose cause is not NoSuchFileException — e.g. read permission denied on the job directory, IO error during traversal, or the path exists but is not a readable directory.

Common situations: Checkpoint directory permissions restricted after job submission; storage volume became read-only or failed; checkpoint data cleaned up concurrently while another process holds a lock; path collision where jobId segment resolves to a regular file.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/f3c1f5ec507b17f4. Report an issue: GitHub.