{"record":{"id":"2fbced94f6beeb40","repo":"risingwavelabs/risingwave","slug":"failed-to-match-fragment-id-message","errorCode":null,"errorMessage":"failed to match fragment {id}: {message}","messagePattern":"failed to match fragment (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/meta/src/stream/stream_graph/state_match.rs","lineNumber":59,"sourceCode":"        let body = node.node_body.as_ref().unwrap();\n\n        Self(format!(\"{}({}, {})\", body, id, identity).into_boxed_str())\n    }\n}\n\nimpl std::fmt::Display for StreamNodeDesc {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self.0)\n    }\n}\n\n/// Error type for failed state table matching.\n#[derive(thiserror::Error, thiserror_ext::Macro, thiserror_ext::ReportDebug)]\npub(crate) enum Error {\n    #[error(\"failed to match graph: {message}\")]\n    Graph { message: String },\n\n    #[error(\"failed to match fragment {id}: {message}\")]\n    Fragment {\n        source: Option<Box<Error>>,\n        id: Id,\n        message: String,\n    },\n\n    #[error(\"failed to match operator {from} to {to}: {message}\")]\n    Operator {\n        from: StreamNodeDesc,\n        to: StreamNodeDesc,\n        message: String,\n    },\n}\n\ntype Result<T, E = Error> = std::result::Result<T, E>;\n\n/// Fragment id.\ntype Id = FragmentId;","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/stream/stream_graph/state_match.rs#L41-L77","documentation":"A `state_match::Error::Fragment` variant raised when the matcher fails to match a whole fragment (identified by `id`) between the old and new stream graph. It carries an optional source chain (`Error`) pointing at the operator-level cause plus a message describing the fragment-level mismatch.","triggerScenarios":"During schema-change state table matching, when a fragment in the new graph cannot be paired with one in the old graph — missing corresponding fragment, changed fragment identity, or a nested operator match error propagated up.","commonSituations":"ALTERs that add/remove/reorder operators so fragment structures differ; jobs where dispatchers or upstream ids changed between versions.","solutions":["Inspect the nested source error to find the operator-level mismatch and address that.","Limit the ALTER to supported column changes that preserve fragment structure; otherwise recreate the streaming job.","Keep frontend and meta on compatible versions so fragment ids/structures remain matchable."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null","typeGuard":"if let state_match::Error::Fragment { id, message, .. } = &err {\n    eprintln!(\"fragment {} mismatched: {}\", id, message);\n}","tryCatchPattern":"match state_match::match_graph(&old, &new) {\n    Err(state_match::Error::Fragment { id, source, .. }) => {\n        tracing::warn!(\"fragment {} unmatched (source: {:?}); consider recreating the job\", id, source);\n    }\n    Err(e) => return Err(e.into()),\n    Ok(tables) => apply(tables),\n}","preventionTips":["Avoid ALTERs that add or remove fragments/structural operators","Version-upgrade jobs in a way that preserves fragment identity","Use recreation for structurally divergent schema changes"],"tags":["meta","schema-change","state-matching"],"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-23T08:17:48.524Z"}