{"record":{"id":"b194fb21fc9b5cc5","repo":"risingwavelabs/risingwave","slug":"invalid-backfill-state-unfinished-row-has-null-cd","errorCode":null,"errorMessage":"invalid backfill state: unfinished row has null cdc_offset","messagePattern":"invalid backfill state: unfinished row has null cdc_offset","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/executor/backfill/cdc/state.rs","lineNumber":86,"sourceCode":"                self.cached_state = row.into_inner().into_vec();\n                let state = self.cached_state.as_slice();\n                let state_len = state.len();\n                // schema: | `split_id` | `pk...` | `backfill_finished` | `row_count` | `cdc_offset` |\n                let row_count = match state[state_len - 2] {\n                    Some(ScalarImpl::Int64(val)) => val,\n                    _ => return Err(anyhow!(\"invalid backfill state: row_count\").into()),\n                };\n                let is_finished = match state[state_len - 3] {\n                    Some(ScalarImpl::Bool(val)) => val,\n                    _ => return Err(anyhow!(\"invalid backfill state: backfill_finished\").into()),\n                };\n                let cdc_offset = match state[state_len - 1] {\n                    Some(ScalarImpl::Jsonb(ref jsonb)) => {\n                        serde_json::from_value(jsonb.clone().take()).unwrap()\n                    }\n                    None if is_finished => None,\n                    None => {\n                        return Err(anyhow!(\n                            \"invalid backfill state: unfinished row has null cdc_offset\"\n                        )\n                        .into());\n                    }\n                    _ => return Err(anyhow!(\"invalid backfill state: cdc_offset\").into()),\n                };\n\n                let current_pk_pos = state[1..state_len - 3].to_vec();\n                Ok(CdcStateRecord {\n                    current_pk_pos: Some(OwnedRow::new(current_pk_pos)),\n                    is_finished,\n                    last_cdc_offset: cdc_offset,\n                    row_count,\n                })\n            }\n            None => Ok(CdcStateRecord::default()),\n        }\n    }","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/executor/backfill/cdc/state.rs#L68-L104","documentation":"The CDC backfill state row's final column is `cdc_offset`, stored as Jsonb. A NULL offset is only legal when `backfill_finished` is true (no offset needed). If the offset is NULL while the backfill is unfinished, the executor cannot resume from a position, so `restore_state` returns this error; a non-Jsonb, non-NULL value yields the sibling 'invalid backfill state: cdc_offset' error.","triggerScenarios":"Recovery of an unfinished CDC backfill whose persisted state row has a NULL `cdc_offset` — state row written without the offset (e.g. partial write or writer bug) while `backfill_finished` is false.","commonSituations":"Crash between writing `backfill_finished=false` state and persisting the offset, version upgrades altering the encoding, or corrupted state store rows.","solutions":["Drop and re-create the CDC table / materialized view using CDC backfill to restart backfill from the snapshot.","Verify no crash occurred mid state-commit (check earlier logs); if so, rebuilding state is the safe path.","Check RisingWave version skew between writer and reader; rebuild state after upgrading.","Inspect the state table row to confirm cdc_offset is NULL and report as a writer bug if reproducible."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure CDC backfill state writes (finished flag + offset) commit together; avoid builds with known partial-write bugs.","Re-create the CDC table when recovery hits this error rather than forcing the backfill to resume.","Keep meta/compute versions aligned and upgrade to patched releases before large backfills."],"tags":["streaming","cdc","backfill","state","recovery"],"backgroundTag":"schema-validation-failed","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}