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
- Inspect the embedded cause message to identify the filesystem failure (permission, IO, etc.).
- Fix directory permissions so the engine user can read the job's checkpoint directory.
- Verify the storage parent directory config resolves to a valid mounted path.
- 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
- Keep the storage volume readable and healthy; monitor disk/mount health.
- Never replace the job directory with a file or symlink loop.
- If the directory may be legitimately absent, delete the whole directory (missing dir is tolerated, listing errors are not).
- Log the embedded cause message to distinguish permissions vs IO failures.
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
- Failed to get all checkpoints for job ${jobId}
- No checkpoint found, job(${jobId}), pipeline(${pipelineId}),
- No checkpoint found for job ${jobId}
- No checkpoint found for job, job id is: ${jobId}
- Skipping checkpoint batch because none of its transactions r
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/f3c1f5ec507b17f4.
Report an issue: GitHub.