{"record":{"id":"1cebb8f90ed8fba4","repo":"risingwavelabs/risingwave","slug":"current-is-checkpoint-does-not-match-with-decod","errorCode":null,"errorMessage":"current is_checkpoint {} does not match with decoded is_checkpoint {}","messagePattern":"current is_checkpoint (.+?) does not match with decoded is_checkpoint (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/common/log_store_impl/kv_log_store/serde.rs","lineNumber":1087,"sourceCode":"                    } else {\n                        match &mut self.stream_state {\n                            StreamState::BarrierAligning {\n                                aligned_vnodes,\n                                read_size,\n                                curr_epoch,\n                                is_checkpoint: current_is_checkpoint,\n                            } => {\n                                aligned_vnodes.set(vnode.to_index(), true);\n                                *read_size += size;\n                                if curr_epoch != &decoded_epoch {\n                                    return Err(anyhow!(\n                                        \"current epoch {} does not match with decoded epoch {}\",\n                                        curr_epoch,\n                                        decoded_epoch\n                                    ));\n                                }\n                                if current_is_checkpoint != &is_checkpoint {\n                                    return Err(anyhow!(\n                                        \"current is_checkpoint {} does not match with decoded is_checkpoint {}\",\n                                        current_is_checkpoint,\n                                        is_checkpoint\n                                    ));\n                                }\n                            }\n                            other => {\n                                let mut aligned_vnodes =\n                                    BitmapBuilder::zeroed(self.serde.vnodes().len());\n                                aligned_vnodes.set(vnode.to_index(), true);\n                                *other = StreamState::BarrierAligning {\n                                    aligned_vnodes,\n                                    read_size: size,\n                                    curr_epoch: decoded_epoch,\n                                    is_checkpoint,\n                                };\n                            }\n                        }","sourceCodeStart":1069,"sourceCodeEnd":1105,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/common/log_store_impl/kv_log_store/serde.rs#L1069-L1105","documentation":"Companion check to the epoch mismatch above: during replay, the in-memory `current_is_checkpoint` flag (whether the barrier being aligned is a checkpoint barrier) does not match the `is_checkpoint` flag decoded from the row. This means two rows decoded as belonging to the same epoch disagree on checkpoint-ness, so the persisted log is internally inconsistent.","triggerScenarios":"During KV log store replay, when `current_is_checkpoint != &is_checkpoint` for rows with the same decoded epoch — e.g. a checkpoint barrier row and a non-checkpoint row share one epoch, or a duplicated/overwritten row carries a different flag.","commonSituations":"Corrupted or partially overwritten metadata KV entries after a crash, mixing logs from different clusters/versions, or a bug writing both checkpoint and non-checkpoint rows under one epoch.","solutions":["Restore the metadata/log store from a consistent snapshot or backup; do not hand-edit the KV store.","Confirm the writing and replaying RisingWave versions match (barrier serialization of `is_checkpoint` may have changed).","If reproducible after a crash, collect the affected key range and file a bug with the recovery logs.","Re-run recovery from the latest checkpoint epoch preceding the corrupted range."],"exampleFix":"// before: manually copying partial metadata between clusters\nscanfh meta-kv --range partial-copy\n// after: restore a full consistent snapshot\nrw meta start --state-store hummock+<original-cluster-snapshot>\n","handlingStrategy":"try-catch","validationCode":"// Validate checkpoint flags are consistent per epoch during a pre-replay scan\nlet mut flags: HashMap<u64, bool> = HashMap::new();\nfor row in scanned_rows {\n    if let Some(prev) = flags.insert(row.epoch(), row.is_checkpoint()) {\n        if prev != row.is_checkpoint() { /* inconsistent epoch flags: abort */ }\n    }\n}","typeGuard":"fn checkpoint_flag_consistent(current: bool, decoded: bool) -> bool { current == decoded }","tryCatchPattern":"// Rust\nmatch log_store.replay(...).await {\n    Err(e) if e.to_string().contains(\"does not match with decoded is_checkpoint\") => {\n        // corrupted/partially overwritten log: restore from consistent snapshot and retry\n    }\n    r => r?,\n}","preventionTips":["Never mix or partially restore log store data between clusters.","Write each epoch's rows atomically so checkpoint and data rows cannot diverge after a crash.","Verify serialization compatibility of barrier flags across RisingWave versions before upgrading in place."],"tags":["streaming","replay","checkpoint","deserialization"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}