{"record":{"id":"0d67e6bc00f5aec7","repo":"apache/seatunnel","slug":"the-job-id-s-has-already-been-submitted-and-is-no","errorCode":null,"errorMessage":"The job id %s has already been submitted and is not starting with a savepoint.","messagePattern":"The job id (.+?) has already been submitted and is not starting with a savepoint\\.","errorType":"exception","errorClass":"JobException","httpStatus":null,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/CoordinatorService.java","lineNumber":1443,"sourceCode":"\n                        jobMaster =\n                                new JobMaster(\n                                        jobId,\n                                        jobImmutableInformation,\n                                        this.nodeEngine,\n                                        mdcExecutorService,\n                                        getResourceManager(),\n                                        getJobHistoryService(),\n                                        runningJobStateIMap,\n                                        runningJobStateTimestampsIMap,\n                                        ownedSlotProfilesIMap,\n                                        runningJobInfoIMap,\n                                        engineConfig,\n                                        seaTunnelServer);\n                        if (!isStartWithSavePoint\n                                && getJobHistoryService().getJobMetrics(jobId)\n                                        != JobMetrics.empty()) {\n                            throw new JobException(\n                                    String.format(\n                                            \"The job id %s has already been submitted and is not starting with a savepoint.\",\n                                            jobId));\n                        }\n                        long initializationTimestamp = System.currentTimeMillis();\n                        submittedJobInfo =\n                                new JobInfo(initializationTimestamp, jobImmutableInformation);\n                        runningJobInfoIMap.put(jobId, submittedJobInfo);\n                        jobMaster.init(initializationTimestamp, false);\n                        // Initialize the JobMaster and add it to the pendingJobQueue, ensuring that\n                        // calling the getJobMaster method does not return NULL when the\n                        // jobSubmitFuture is still running.\n                        PendingJobInfo pendingJobInfo =\n                                new PendingJobInfo(PendingSourceState.SUBMIT, jobMaster);\n                        pendingJobQueue.put(pendingJobInfo);\n                        // We specify that when init is complete, the submitJob is complete.\n                        jobSubmitFuture.complete(null);\n                    } catch (Throwable e) {","sourceCodeStart":1425,"sourceCodeEnd":1461,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/CoordinatorService.java#L1425-L1461","documentation":"On submission with an explicit jobId, the engine checks job history metrics to detect duplicate submissions. If non-empty metrics already exist for that jobId (a job with that id was previously submitted) and the request is not a savepoint/restore start, submission fails with this JobException. It prevents silently reusing a job id that already has history.","triggerScenarios":"submitJob called with a jobId whose job history metrics are non-empty, with isStartWithSavePoint=false.","commonSituations":"Hardcoded jobId in a shared config or script executed twice; replaying an old job config that still contains its original jobId; CI pipelines resubmitting without id generation.","solutions":["Do not set a fixed jobId; let the engine generate a new unique id per submission.","Use start-with-savepoint if you intentionally want to resume a job under the same id.","Check job history (getJobMetrics / REST jobinfo) before submitting with a custom id.","Centralize job id generation (e.g. new Random().nextLong()) in submission tooling."],"exampleFix":"// before\nlong jobId = 861912345L; // id copied from an old config\nclient.submitJob(jobId, config, false);\n// after\nlong jobId = new Random().nextLong();\nclient.submitJob(jobId, config, false);","handlingStrategy":"validation","validationCode":"// ensure the id is unused before a non-savepoint submission\nJobMetrics existing = jobClient.getJobMetrics(jobId);\nif (existing != null && !existing.equals(JobMetrics.empty())) {\n    jobId = new Random().nextLong();\n}","typeGuard":null,"tryCatchPattern":"try {\n    client.submitJob(jobId, config, false);\n} catch (JobException e) {\n    if (e.getMessage().contains(\"has already been submitted\")) {\n        client.submitJob(new Random().nextLong(), config, false);\n    } else { throw e; }\n}","preventionTips":["Never hardcode jobId in shared job configs or scripts.","Strip old jobId values when replaying historical job configs.","Centralize job id generation in submission tooling.","Use savepoint start when intentionally resuming under an existing id."],"tags":["zeta-engine","job-submission","duplicate-jobid"],"backgroundTag":"invalid-state-transition","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}