apache/seatunnel · error · IllegalArgumentException

--restore and --restore-with-checkpoint are mutually exclusi

Error message

--restore and --restore-with-checkpoint are mutually exclusive

What it means

ClientCommandArgs.buildCommand validates CLI options before building the client command. Passing both --restore (restore from a saved state/savepoint) and --restore-with-checkpoint (restore from the latest checkpoint) is rejected, because a job can only be restored from one source. Thrown as IllegalArgumentException at argument-parsing time.

Source

Thrown at seatunnel-core/seatunnel-starter/src/main/java/org/apache/seatunnel/core/starter/seatunnel/args/ClientCommandArgs.java:170

            description = "list job status")
    private boolean listJob = false;

    @Parameter(
            names = {"--async"},
            description =
                    "Run the job asynchronously, when the job is submitted, the client will exit")
    private boolean async = false;

    @Parameter(
            names = {"-cj", "--close", "--close-job"},
            description = "Close client the task will also be closed")
    private boolean closeJob = true;

    @Override
    public Command<?> buildCommand() {
        validateCommandOptions();
        if (restoreJobId != null && restoreWithCheckpointJobId != null) {
            throw new IllegalArgumentException(
                    "--restore and --restore-with-checkpoint are mutually exclusive");
        }
        if (savePointJobId != null && restoreWithCheckpointJobId != null) {
            throw new IllegalArgumentException(
                    "--savepoint and --restore-with-checkpoint are mutually exclusive");
        }
        if (restoreWithCheckpointJobId != null) {
            restoreWithCheckpointJobId =
                    normalizeNumericJobId(
                            restoreWithCheckpointJobId,
                            "restoreSourceJobId is required when using --restore-with-checkpoint",
                            "--restore-with-checkpoint requires a numeric jobId, got: ");
        }
        if (customJobId != null) {
            customJobId =
                    normalizeNumericJobId(
                            customJobId,
                            "--set-job-id requires a non-blank jobId",

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Remove one of the two flags; keep only the restore mechanism you want
  2. Use --restore <jobId> to restore from a savepoint, or --restore-with-checkpoint <jobId> to restore from the latest checkpoint — not both
  3. Update wrapper scripts to emit exactly one restore flag

Example fix

// before
--restore 12345 --restore-with-checkpoint 12345
// after
--restore-with-checkpoint 12345
Defensive patterns

Strategy: validation

Validate before calling

if (args.has("restore") && args.has("restore-with-checkpoint")) {
    throw new IllegalArgumentException("pass only one of --restore / --restore-with-checkpoint");
}

Type guard

boolean hasConflictingRestoreFlags(String[] cliArgs) {
    boolean r = false, rc = false;
    for (String a : cliArgs) {
        if (a.startsWith("--restore ") || a.equals("--restore")) r = true;
        if (a.startsWith("--restore-with-checkpoint")) rc = true;
    }
    return r && rc;
}

Try / catch

try {
    client.submit(args);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("mutually exclusive")) {
        log.error("Remove one of the conflicting flags: " + e.getMessage());
    }
}

Prevention

When it happens

Trigger: Submitting a job with both --restore <jobId> and --restore-with-checkpoint <jobId> on the command line (or both set programmatically on ClientCommandArgs before buildCommand()).

Common situations: Script templating that unconditionally appends both flags; migrating scripts from --restore to the newer --restore-with-checkpoint while keeping the old flag; confusion between the two restore mechanisms.

Understand the failure class

Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.

Related errors


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