{"record":{"id":"3f14e7c20b7bd026","repo":"apache/iceberg","slug":"failed-to-load-committed-snapshot-omitting-sequen","errorCode":null,"errorMessage":"Failed to load committed snapshot: omitting sequence number from notifications","messagePattern":"Failed to load committed snapshot: omitting sequence number from notifications","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/apache/iceberg/MergingSnapshotProducer.java","lineNumber":1101,"sourceCode":"    return manifests;\n  }\n\n  @Override\n  public Object updateEvent() {\n    long snapshotId = snapshotId();\n\n    Snapshot justSaved = ops().current().snapshot(snapshotId);\n    if (justSaved == null) {\n      justSaved = ops().refresh().snapshot(snapshotId);\n    }\n\n    long sequenceNumber = TableMetadata.INVALID_SEQUENCE_NUMBER;\n    Map<String, String> summary;\n    if (justSaved == null) {\n      // The snapshot just saved may not be present if the latest metadata couldn't be loaded due to\n      // eventual\n      // consistency problems in refresh.\n      LOG.warn(\"Failed to load committed snapshot: omitting sequence number from notifications\");\n      summary = summary();\n    } else {\n      sequenceNumber = justSaved.sequenceNumber();\n      summary = justSaved.summary();\n    }\n\n    return new CreateSnapshotEvent(tableName, operation(), snapshotId, sequenceNumber, summary);\n  }\n\n  @Override\n  protected void cleanUncommitted(Set<ManifestFile> committed) {\n    mergeManager.cleanUncommitted(committed);\n    filterManager.cleanUncommitted(committed);\n    deleteMergeManager.cleanUncommitted(committed);\n    deleteFilterManager.cleanUncommitted(committed);\n    cleanUncommittedAppends(committed);\n  }\n","sourceCodeStart":1083,"sourceCodeEnd":1119,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/MergingSnapshotProducer.java#L1083-L1119","documentation":"After committing a snapshot, MergingSnapshotProducer notifies listeners using the just-saved snapshot. If the snapshot cannot be found in the (refreshed) table metadata — typically because the latest metadata couldn't be loaded due to eventual-consistency problems during refresh — this WARN is logged, the sequence number is set to INVALID_SEQUENCE_NUMBER, and notifications are emitted without it.","triggerScenarios":"A commit succeeds on the catalog, then table.refresh()/loading the current metadata fails to observe the new snapshot immediately (eventually consistent catalog or object store); notify listeners path runs with justSaved == null.","commonSituations":"Eventually consistent object stores (e.g. S3 without strong read-after-write) backing a Hadoop/FileIO catalog; slow catalog propagation right after commit; listeners (e.g. Spark listener buses, event hooks) observing notifications missing sequence numbers.","solutions":["Use a catalog/storage backend with strong read-after-write consistency so the committed snapshot is immediately visible on refresh.","Retry the refresh or add a short delay before reading metadata in code that triggers notification right after commit.","If you consume notifications downstream, tolerate a null/invalid sequence number rather than assuming it is always set.","Upgrade the catalog implementation if known eventual-consistency behavior is causing frequent occurrences."],"exampleFix":"// before (listener assumes sequence number always present)\nlong seq = notification.sequenceNumber();\n// after\nlong seq = notification.sequenceNumber() != TableMetadata.INVALID_SEQUENCE_NUMBER\n    ? notification.sequenceNumber()\n    : -1L; // handle missing sequence number","handlingStrategy":"try-catch","validationCode":"// after commit, confirm the snapshot is visible before notifying\nif (table.operations().current().snapshot(snapshotId) == null) {\n  // metadata not yet visible (eventual consistency) — handle missing sequence number\n}","typeGuard":"static boolean hasSequenceNumber(Snapshot s) {\n  return s != null && s.sequenceNumber() != TableMetadata.INVALID_SEQUENCE_NUMBER;\n}","tryCatchPattern":"try {\n  long seq = justSaved.sequenceNumber();\n} catch (NullPointerException | IllegalStateException e) {\n  long seq = TableMetadata.INVALID_SEQUENCE_NUMBER; // degrade notifications\n}","preventionTips":["Use strongly consistent catalogs/stores so committed snapshots are visible immediately.","Design downstream notification consumers to tolerate invalid/absent sequence numbers.","Add retry/delay around refresh-after-commit in custom commit flows.","Track how often this WARN fires as an eventual-consistency signal for your storage."],"tags":["eventual-consistency","commits","snapshots","notifications"],"backgroundTag":"eventual-consistency","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}