apache/seatunnel · error · JobException

restoreSourceJobId must reference a historical terminal sour

Error message

restoreSourceJobId must reference a historical terminal source job when restoreMode=CHECKPOINT

What it means

CheckpointRestoreValidator rejects self-referencing restores: restoreSourceJobId must point to a different, historical job that reached a terminal state. If the provided id equals the destination job's own id, validation fails since a job cannot restore checkpoints from itself.

Source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/CheckpointRestoreValidator.java:47

    private CheckpointRestoreValidator() {}

    static void validate(
            JobImmutableInformation jobImmutableInformation,
            long destinationJobId,
            LongFunction<JobStatus> activeSourceJobStatusResolver) {
        if (jobImmutableInformation == null
                || jobImmutableInformation.getRestoreMode() != RestoreMode.CHECKPOINT) {
            return;
        }

        Long restoreSourceJobId = jobImmutableInformation.getRestoreSourceJobId();
        if (restoreSourceJobId == null) {
            throw new JobException(
                    "restoreSourceJobId is required when restoreMode="
                            + jobImmutableInformation.getRestoreMode());
        }
        if (restoreSourceJobId == destinationJobId) {
            throw new JobException(
                    "restoreSourceJobId must reference a historical terminal source job when restoreMode=CHECKPOINT");
        }

        JobStatus sourceJobStatus =
                activeSourceJobStatusResolver == null
                        ? null
                        : activeSourceJobStatusResolver.apply(restoreSourceJobId);
        if (sourceJobStatus != null && !sourceJobStatus.isEndState()) {
            throw new JobException(
                    String.format(
                            "checkpoint restore requires a terminal source job, restoreSourceJobId=%s, current source job status=%s",
                            restoreSourceJobId, sourceJobStatus));
        }
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Supply the id of the ORIGINAL historical job whose checkpoints should be restored.
  2. Ensure the destination job id is generated fresh for the new submission, not copied from the source.
  3. Check automation scripts for a variable shadowing the two ids.

Example fix

// before: same id for both
Long jobId = 883745192014848L;
builder.restoreMode(CHECKPOINT).restoreSourceJobId(jobId).jobId(jobId);
// after
builder.jobId(newRandomJobId()).restoreMode(CHECKPOINT).restoreSourceJobId(883745192014848L);
Defensive patterns

Strategy: validation

Validate before calling

if (restoreMode == RestoreMode.CHECKPOINT && restoreSourceJobId.equals(destinationJobId)) {
  throw new IllegalArgumentException("restoreSourceJobId must differ from the new job id");
}

Try / catch

try {
  client.submitJob(request);
} catch (JobException e) {
  if (e.getMessage().contains("must reference a historical terminal source job")) {
    // regenerate destination job id, keep original source id
  }
}

Prevention

When it happens

Trigger: validate() is called with restoreMode=CHECKPOINT and restoreSourceJobId == destinationJobId (both ids identical) during job submission.

Common situations: Script or automation reusing the same variable for the new job id and the restore source id; copy-paste of the job id field into the restore field; retry loops resubmitting with the previous (rejected) job id.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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