apache/seatunnel · error · IllegalStateException

schema-change-after checkpoint is already completed, job id:

Error message

schema-change-after checkpoint is already completed, job id: %s, pipeline id: %s, checkpoint id: %s.

What it means

Thrown when the coordinator is asked to trigger a schema-change-after checkpoint, but that checkpoint has already completed — it is tracked as completed, so triggering another one is an invalid state transition. IllegalStateException signals a caller sequencing bug rather than a user config problem.

Source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/checkpoint/CheckpointCoordinator.java:1568

    }

    protected void completeSchemaChangeAfterCheckpoint(CompletedCheckpoint checkpoint) {
        if (schemaChanging.compareAndSet(true, false)) {
            LOG.info(
                    "completed schema-change-after checkpoint, job id: {}, pipeline id: {}, "
                            + "checkpoint id: {}.",
                    jobId,
                    pipelineId,
                    checkpoint.getCheckpointId());
            LOG.info(
                    "recover trigger general-checkpoint, job id: {}, pipeline id: {}, "
                            + "checkpoint id: {}.",
                    jobId,
                    pipelineId,
                    checkpoint.getCheckpointId());
            scheduleTriggerPendingCheckpoint(coordinatorConfig.getCheckpointInterval());
        } else {
            throw new IllegalStateException(
                    String.format(
                            "schema-change-after checkpoint is already completed, "
                                    + "job id: %s, pipeline id: %s, checkpoint id: %s.",
                            jobId, pipelineId, checkpoint.getCheckpointId()));
        }
    }

    public String getCheckpointStateImapKey() {
        return checkpointStateImapKey;
    }

    public String getReadyToCloseImapKey() {
        return readyToCloseImapKey;
    }

    /** Only for test */
    @VisibleForTesting
    public PendingCheckpoint getSavepointPendingCheckpoint() {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Check checkpoint state before triggering: skip if the schema-change-after checkpoint is already completed (the normal path already reschedules the interval checkpoint)
  2. Deduplicate schema-change trigger notifications (idempotency by checkpointId) at the caller
  3. Serialize schema-change requests per pipeline so concurrent triggers can't race past the completed check
  4. If the error comes from a retry path, treat 'already completed' as success and continue rather than failing the job

Example fix

// before
coordinator.triggerSchemaChangeCheckpoint(checkpointId); // may already be completed

// after
if (!coordinator.isSchemaChangeCheckpointCompleted(checkpointId)) {
    coordinator.triggerSchemaChangeCheckpoint(checkpointId);
} else {
    LOG.info("Schema-change checkpoint {} already completed, skipping", checkpointId);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (isSchemaChangeCheckpointCompleted(jobId, pipelineId, checkpointId)) {
    return; // already done, nothing to trigger
}

Try / catch

try {
    triggerSchemaChangeCheckpoint(checkpointId);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("already completed")) {
        LOG.info("Schema-change checkpoint already done; treating as success");
    } else { throw e; }
}

Prevention

When it happens

Trigger: Requesting/advancing a schema-change-after checkpoint for a (jobId, pipelineId, checkpointId) whose state is already COMPLETED — e.g., a duplicate schema-change trigger, a retried notification after the checkpoint finished, or concurrent schema-change requests racing.

Common situations: Schema evolution events delivered twice (retries from the catalog/source); a schema change arriving right after the schema-change checkpoint finished; concurrent connectors each triggering the same schema-change checkpoint.

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/bbf4ec592f7a4c63. Report an issue: GitHub.