apache/iceberg · error · ValidationException
Cannot apply non-unique WAP ID. Found multiple snapshots wit
Error message
Cannot apply non-unique WAP ID. Found multiple snapshots with WAP ID '%s'
What it means
PublishChangesProcedure cherry-picks a staged (write-audit-publish) snapshot identified by its 'wap.id' snapshot summary property. Before publishing, it scans all snapshots for the given WAP ID; if two or more staged snapshots carry the same ID, it aborts, because it cannot determine which snapshot to publish. This guards against reusing a WAP ID across commits.
Source
Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/procedures/PublishChangesProcedure.java:102
public ProcedureParameter[] parameters() {
return PARAMETERS;
}
@Override
public Iterator<Scan> call(InternalRow args) {
ProcedureInput input = new ProcedureInput(spark(), tableCatalog(), PARAMETERS, args);
Identifier tableIdent = input.ident(TABLE_PARAM);
String wapId = input.asString(WAP_ID_PARAM);
return modifyIcebergTable(
tableIdent,
table -> {
Snapshot matchingSnap = null;
for (Snapshot snap : table.snapshots()) {
if (wapId.equals(WapUtil.stagedWapId(snap))) {
if (matchingSnap != null) {
throw new ValidationException(
"Cannot apply non-unique WAP ID. Found multiple snapshots with WAP ID '%s'",
wapId);
} else {
matchingSnap = snap;
}
}
}
if (matchingSnap == null) {
throw new ValidationException("Cannot apply unknown WAP ID '%s'", wapId);
}
long wapSnapshotId = matchingSnap.snapshotId();
table.manageSnapshots().cherrypick(wapSnapshotId).commit();
Snapshot currentSnapshot = table.currentSnapshot();
InternalRow outputRow = newInternalRow(wapSnapshotId, currentSnapshot.snapshotId());
return asScanIterator(OUTPUT_TYPE, outputRow);
});View on GitHub (pinned to 86d9c8fc54)
Solutions
- Ensure each staged write gets a unique WAP ID (per-run UUID), e.g. derive spark.wap.id per execution.
- Expire or delete the stale staged snapshots so only one carries the ID, then retry publish.
- Publish the specific snapshot explicitly instead: cherry-pick the desired snapshotId via manageSnapshots/rewrite the procedure call.
- Audit the writer configuration generating wap.id for reuse.
Example fix
// before (reused static id)
spark.conf.set("spark.wap.id", "run-42");
// after (unique per run)
spark.conf.set("spark.wap.id", java.util.UUID.randomUUID().toString()); Defensive patterns
Strategy: validation
Validate before calling
SELECT snapshot_id, summary['wap.id'] FROM db.t.snapshots WHERE summary['wap.id'] = 'my-id'; // expect exactly one row
Try / catch
try { publishChanges(table, wapId); } catch (ValidationException e) { /* duplicate WAP ID: expire stale snapshot or use unique IDs */ } Prevention
- Generate a fresh UUID per write for spark.wap.id.
- Never hardcode a static WAP ID across runs.
- Expire stale staged snapshots before re-staging.
When it happens
Trigger: Calling CALL iceberg.system.publish_changes(table => 'db.t', wap_id => 'some-id') when the table's history contains two staged snapshots both stamped with that same wap.id — typically because a writer reused a fixed wap.id value across multiple writes without publishing in between.
Common situations: A Spark job sets spark.wap.id to a static value in config instead of a per-run UUID; two concurrent/staged branches of the same job write with the same WAP ID; a failed publish followed by a re-run staged a second snapshot with the same ID.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Cannot apply non-unique WAP ID. Found multiple snapshots wit
- Cannot apply non-unique WAP ID. Found multiple snapshots wit
- Cannot apply unknown WAP ID '${wapId}'
- Cannot apply unknown WAP ID '%s'
- Cannot apply unknown WAP ID '%s'
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/5710ccbc41cb3340.
Report an issue: GitHub.