apache/seatunnel · error · JobException

The job id %s has already been submitted and is not starting

Error message

The job id %s has already been submitted and is not starting with a savepoint.

What it means

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.

Source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/CoordinatorService.java:1443

                        jobMaster =
                                new JobMaster(
                                        jobId,
                                        jobImmutableInformation,
                                        this.nodeEngine,
                                        mdcExecutorService,
                                        getResourceManager(),
                                        getJobHistoryService(),
                                        runningJobStateIMap,
                                        runningJobStateTimestampsIMap,
                                        ownedSlotProfilesIMap,
                                        runningJobInfoIMap,
                                        engineConfig,
                                        seaTunnelServer);
                        if (!isStartWithSavePoint
                                && getJobHistoryService().getJobMetrics(jobId)
                                        != JobMetrics.empty()) {
                            throw new JobException(
                                    String.format(
                                            "The job id %s has already been submitted and is not starting with a savepoint.",
                                            jobId));
                        }
                        long initializationTimestamp = System.currentTimeMillis();
                        submittedJobInfo =
                                new JobInfo(initializationTimestamp, jobImmutableInformation);
                        runningJobInfoIMap.put(jobId, submittedJobInfo);
                        jobMaster.init(initializationTimestamp, false);
                        // Initialize the JobMaster and add it to the pendingJobQueue, ensuring that
                        // calling the getJobMaster method does not return NULL when the
                        // jobSubmitFuture is still running.
                        PendingJobInfo pendingJobInfo =
                                new PendingJobInfo(PendingSourceState.SUBMIT, jobMaster);
                        pendingJobQueue.put(pendingJobInfo);
                        // We specify that when init is complete, the submitJob is complete.
                        jobSubmitFuture.complete(null);
                    } catch (Throwable e) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Do not set a fixed jobId; let the engine generate a new unique id per submission.
  2. Use start-with-savepoint if you intentionally want to resume a job under the same id.
  3. Check job history (getJobMetrics / REST jobinfo) before submitting with a custom id.
  4. Centralize job id generation (e.g. new Random().nextLong()) in submission tooling.

Example fix

// before
long jobId = 861912345L; // id copied from an old config
client.submitJob(jobId, config, false);
// after
long jobId = new Random().nextLong();
client.submitJob(jobId, config, false);
Defensive patterns

Strategy: validation

Validate before calling

// ensure the id is unused before a non-savepoint submission
JobMetrics existing = jobClient.getJobMetrics(jobId);
if (existing != null && !existing.equals(JobMetrics.empty())) {
    jobId = new Random().nextLong();
}

Try / catch

try {
    client.submitJob(jobId, config, false);
} catch (JobException e) {
    if (e.getMessage().contains("has already been submitted")) {
        client.submitJob(new Random().nextLong(), config, false);
    } else { throw e; }
}

Prevention

When it happens

Trigger: submitJob called with a jobId whose job history metrics are non-empty, with isStartWithSavePoint=false.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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