{"record":{"id":"6c9cb3d75e285aa0","repo":"apache/seatunnel","slug":"no-checkpoint-found-for-job-jobid","errorCode":null,"errorMessage":"No checkpoint found for job ${jobId}","messagePattern":"No checkpoint found for job (.+?)","errorType":"exception","errorClass":"CheckpointStorageException","httpStatus":null,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-local-file/src/main/java/org/apache/seatunnel/engine/checkpoint/storage/localfile/LocalFileStorage.java","lineNumber":337,"sourceCode":"                String.format(\n                        \"No checkpoint found, job(%s), pipeline(%s), checkpoint(%s)\",\n                        jobId, pipelineId, checkpointId));\n    }\n\n    @Override\n    public synchronized void deleteCheckpoint(String jobId, String pipelineId, String checkpointId)\n            throws CheckpointStorageException {\n        String parentPath = getStorageParentDirectory() + jobId;\n        Collection<File> fileList = new ArrayList<>();\n        try {\n            fileList = FileUtils.listFiles(new File(parentPath), FILE_EXTENSIONS, false);\n        } catch (Exception e) {\n            if (!(e.getCause() instanceof NoSuchFileException)) {\n                throw new CheckpointStorageException(ExceptionUtils.getMessage(e));\n            }\n        }\n        if (fileList.isEmpty()) {\n            throw new CheckpointStorageException(\"No checkpoint found for job \" + jobId);\n        }\n        fileList.forEach(\n                file -> {\n                    String fileName = file.getName();\n                    if (pipelineId.equals(getPipelineIdByFileName(fileName))\n                            && checkpointId.equals(getCheckpointIdByFileName(fileName))) {\n                        try {\n                            FileUtils.delete(file);\n                        } catch (Exception e) {\n                            log.error(\n                                    \"Failed to delete checkpoint {} for job {}, pipeline {}\",\n                                    checkpointId,\n                                    jobId,\n                                    pipelineId,\n                                    e);\n                        }\n                    }\n                });","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-local-file/src/main/java/org/apache/seatunnel/engine/checkpoint/storage/localfile/LocalFileStorage.java#L319-L355","documentation":"LocalFileStorage.deleteCheckpoint(jobId, pipelineId, checkpointId) throws 'No checkpoint found for job <jobId>' when the job's checkpoint directory lists successfully but contains no checkpoint files at all. The delete API requires existing checkpoints to operate on; an empty job directory is treated as an error rather than a no-op, so callers cannot blindly call delete on already-cleaned jobs.","triggerScenarios":"Calling deleteCheckpoint(jobId, pipelineId, checkpointId) after all checkpoint files were already deleted (e.g. by a prior delete call or external cleanup), or when the job directory exists but is empty because checkpoints were never successfully written.","commonSituations":"Double-invocation of cleanup logic (job finished listener firing twice); checkpoint writes never happened because the job failed before the first completed checkpoint; an external retention job emptied the directory between listing and delete; id mismatch — files exist for other pipelines but the directory filter yields nothing (note this specific message fires only when the whole job file list is empty).","solutions":["Make delete idempotent on your side: check for existing checkpoints (getCheckpointsByJobIdAndPipelineId) before calling deleteCheckpoint and skip when empty.","Catch CheckpointStorageException and treat the 'No checkpoint found for job' message as success in cleanup paths.","Investigate why checkpoints are missing — check earlier logs for failed checkpoint writes.","If deleting a specific pipeline/checkpoint, verify the id strings match exactly what was written (pipeline id and checkpoint id formatting must match)."],"exampleFix":"// before\nstorage.deleteCheckpoint(jobId, pipelineId, checkpointId); // throws if nothing stored\n// after\ntry {\n    storage.deleteCheckpoint(jobId, pipelineId, checkpointId);\n} catch (CheckpointStorageException e) {\n    if (!e.getMessage().contains(\"No checkpoint found\")) {\n        throw e;\n    }\n    log.info(\"Checkpoints already removed for job {}\", jobId);\n}","handlingStrategy":"try-catch","validationCode":"// Only call delete when checkpoints actually exist\nif (storage.getCheckpointsByJobIdAndPipelineId(jobId, pipelineId).isEmpty()) {\n    return; // nothing to delete\n}","typeGuard":null,"tryCatchPattern":"try {\n    storage.deleteCheckpoint(jobId, pipelineId, checkpointId);\n} catch (CheckpointStorageException e) {\n    if (e.getMessage().startsWith(\"No checkpoint found\")) {\n        log.info(\"Nothing to delete for job {} — already clean\", jobId);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Make cleanup idempotent — treat 'no checkpoint found' as success.","Avoid double-invoking job-finished cleanup listeners.","Verify the job ever wrote a completed checkpoint before attempting deletes.","Do not run external retention sweeps concurrently with application cleanup."],"tags":["checkpoint","local-file-storage","delete","not-found"],"backgroundTag":"file-not-found","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}