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
- Check checkpoint state before triggering: skip if the schema-change-after checkpoint is already completed (the normal path already reschedules the interval checkpoint)
- Deduplicate schema-change trigger notifications (idempotency by checkpointId) at the caller
- Serialize schema-change requests per pipeline so concurrent triggers can't race past the completed check
- 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
- Make schema-change triggers idempotent per checkpointId
- Serialize schema-change requests per pipeline
- Ignore duplicate trigger notifications from sources/catalogs
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
- Unknown checkpoint type:
- checkpoint restore requires a terminal source job, restoreSo
- The job with id '%s' save point failed
- Failed to load readyToCloseStartingTask from IMap, key: %s
- Failed to persist readyToCloseStartingTask to IMap, key: %s
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/bbf4ec592f7a4c63.
Report an issue: GitHub.