apache/iceberg · error · ValidationException
Cannot apply unknown WAP ID '${wapId}'
Error message
Cannot apply unknown WAP ID '${wapId}' What it means
publish_changes scans all table snapshots for one whose wap-id property equals the supplied wap_id argument. If none matches, it throws ValidationException — no staged snapshot exists under that ID to publish.
Source
Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/procedures/PublishChangesProcedure.java:107
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 new InternalRow[] {outputRow};
});
}
@Override
public String description() {
return "ApplyWapChangesProcedure";
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check staged snapshots via the snapshots metadata table for the exact wap-id value.
- Confirm the write job actually committed with wap staging enabled (spark.wap.enabled=true).
- Re-run the staged write to create the snapshot, then publish with the exact ID.
- If snapshots were expired, republish from a fresh staged write.
Example fix
// before
spark.sql("CALL cat.system.publish_changes(wap_id => 'run-42')") // no such staged snapshot
// after
// verify staged snapshot exists in cat.db.t.snapshots with wap-id='run-42' first
spark.sql("CALL cat.system.publish_changes(wap_id => 'run-42')") Defensive patterns
Strategy: validation
Validate before calling
long matches = spark.read().format("iceberg").load("cat.db.t.snapshots")
.filter("snapshot_props['wap-id'] = '" + wapId + "'").count();
if (matches == 0) throw new IllegalStateException("Unknown WAP ID: " + wapId); Try / catch
try { spark.sql("CALL cat.system.publish_changes(wap_id => '" + wapId + "')"); } catch (ValidationException e) { if (e.getMessage().contains("unknown WAP ID")) { /* verify staged write committed, then retry with correct ID */ } throw e; } Prevention
- Pass the exact spark.wap.id value from the write job to publish_changes.
- Confirm the staged write committed successfully before publishing.
- Remember expire_snapshots can remove staged snapshots; publish promptly.
- Log the WAP ID from the writer and reuse it verbatim.
When it happens
Trigger: Calling `CALL cat.system.publish_changes(wap_id => 'xyz')` where no snapshot has property wap-id='xyz' — the staged write never committed, failed, was already published, or the ID string differs (case/whitespace).
Common situations: Copy-pasting WAP IDs between jobs; write job failure before commit; expire_snapshots removing the staged snapshot; typos in the wap_id argument.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 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 '%s'
- Cannot apply non-unique WAP ID. Found multiple snapshots wit
- Cannot apply unknown WAP ID '%s'
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/2f6d916ad1f10b50.
Report an issue: GitHub.