{"record":{"id":"0d7b902179d233d8","repo":"diem/diem","slug":"transaction-versions-are-not-consecutive","errorCode":null,"errorMessage":"Transaction versions are not consecutive.","messagePattern":"Transaction versions are not consecutive\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"storage/diemdb/src/transaction_store/mod.rs","lineNumber":160,"sourceCode":"        Ok(())\n    }\n}\n\npub struct TransactionIter<'a> {\n    inner: SchemaIterator<'a, TransactionSchema>,\n    expected_next_version: Version,\n    end_version: Version,\n}\n\nimpl<'a> TransactionIter<'a> {\n    fn next_impl(&mut self) -> Result<Option<Transaction>> {\n        if self.expected_next_version >= self.end_version {\n            return Ok(None);\n        }\n\n        let ret = match self.inner.next().transpose()? {\n            Some((version, transaction)) => {\n                ensure!(\n                    version == self.expected_next_version,\n                    \"Transaction versions are not consecutive.\",\n                );\n                self.expected_next_version += 1;\n                Some(transaction)\n            }\n            None => None,\n        };\n\n        Ok(ret)\n    }\n}\n\nimpl<'a> Iterator for TransactionIter<'a> {\n    type Item = Result<Transaction>;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        self.next_impl().transpose()","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/diem/diem/blob/fc4714a8ea273b6efe8b13dbce72ea60aad9a16c/storage/diemdb/src/transaction_store/mod.rs#L142-L178","documentation":"The transaction store's ledger-info iterator (next_impl) walks consecutive transaction versions from start_version to end_version. DiemDB guarantees every version in a committed range exists, so if the underlying CF iterator yields a version other than expected_next_version, the DB is missing or has extra versions and is considered corrupt.","triggerScenarios":"Iterating transactions via get_transactions / the TransactionStore iterator over a range where a version entry is missing or duplicated in the transaction CF, so the next item's version != expected_next_version.","commonSituations":"Corrupted or manually pruned RocksDB data, restoring partial backups that skip version ranges, or hardware/disk issues dropping SST entries.","solutions":["Treat the DB as corrupt: re-sync the node from a trusted snapshot or genesis.","Verify the transaction CF with diem-db-tooling / inspector to find the gap.","Ensure no external pruning job removed versions inside ranges still being iterated."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Before iterating, confirm the DB is healthy:\nlet startup = db.get_startup_info().expect(\"db open\");\nlet latest = startup.unwrap().latest_ledger_info.ledger_info().version();\nassert!(start <= end && end <= latest, \"requested range beyond stored versions\");","typeGuard":null,"tryCatchPattern":"match iter_result {\n    Err(e) if e.to_string().contains(\"not consecutive\") => {\n        error!(\"transaction store corrupt at {}..{}\", start, end); \n        // halt, alert, re-sync from snapshot\n    }\n    other => other?,\n}","preventionTips":["Do not run external pruning inside version ranges still served to clients.","Always restore full, verified snapshots; never splice partial DB directories.","Monitor RocksDB for corruption events and alerts.","Keep periodic backups so re-sync cost is bounded."],"tags":["storage","rocksdb","corruption","consistency"],"backgroundTag":"db-corruption-version-gap","analyzedSha":"fc4714a8ea273b6efe8b13dbce72ea60aad9a16c","analyzedAt":"2026-09-04T21:07:05.890Z","contentChangedAt":"2026-09-04T21:07:05.890Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}