{"record":{"id":"e4ccc72cd3de8a6d","repo":"risingwavelabs/risingwave","slug":"source-backfill-fragment-s-upstream-fragment-shoul","errorCode":null,"errorMessage":"source backfill fragment's upstream fragment should have one-on-one no_shuffle mapping, fragment_id: {fragment_id}, upstream_fragment_id: {upstream_source_fragment_id}, actor_no_shuffle: {actor_no_shuffle:?}","messagePattern":"source backfill fragment's upstream fragment should have one-on-one no_shuffle mapping, fragment_id: (.+?), upstream_fragment_id: (.+?), actor_no_shuffle: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/stream/source_manager/split_assignment.rs","lineNumber":302,"sourceCode":"                let upstream_actors: HashSet<ActorId> = actor_no_shuffle\n                    .get(&upstream_source_fragment_id)\n                    .and_then(|m| m.get(&fragment_id))\n                    .ok_or_else(|| {\n                        anyhow!(\n                            \"no upstream actors found from fragment {} to upstream source fragment {}\",\n                            fragment_id,\n                            upstream_source_fragment_id\n                        )\n                    })?.keys().copied().collect();\n\n                let mut backfill_actors = vec![];\n                let Some(source_new_no_shuffle) = actor_no_shuffle\n                    .get(&upstream_source_fragment_id)\n                    .and_then(|source_upstream_actor_no_shuffle| {\n                        source_upstream_actor_no_shuffle.get(&fragment_id)\n                    })\n                else {\n                    return Err(anyhow::anyhow!(\n                            \"source backfill fragment's upstream fragment should have one-on-one no_shuffle mapping, fragment_id: {fragment_id}, upstream_fragment_id: {upstream_source_fragment_id}, actor_no_shuffle: {actor_no_shuffle:?}\",\n                            fragment_id = fragment_id,\n                            upstream_source_fragment_id = upstream_source_fragment_id,\n                            actor_no_shuffle = actor_no_shuffle,\n                        ).into());\n                };\n                for upstream_actor in &upstream_actors {\n                    let Some(no_shuffle_backfill_actor) = source_new_no_shuffle.get(upstream_actor)\n                    else {\n                        return Err(anyhow::anyhow!(\n                            \"source backfill fragment's upstream fragment should have one-on-one no_shuffle mapping, fragment_id: {fragment_id}, upstream_fragment_id: {upstream_source_fragment_id}, upstream_actor: {upstream_actor}, source_new_no_shuffle: {source_new_no_shuffle:?}\",\n                            fragment_id = fragment_id,\n                            upstream_source_fragment_id = upstream_source_fragment_id,\n                            upstream_actor = upstream_actor,\n                            source_new_no_shuffle = source_new_no_shuffle\n                        ).into());\n                    };\n                    backfill_actors.push((*no_shuffle_backfill_actor, *upstream_actor));","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/stream/source_manager/split_assignment.rs#L284-L320","documentation":"resolve_backfill_splits requires the upstream source fragment to have a one-on-one no_shuffle mapping to the source backfill fragment. This error fires when the entry `actor_no_shuffle[upstream_fragment][fragment]` is entirely absent, meaning the expected 1:1 topology invariant does not hold.","triggerScenarios":"Source backfill split resolution where the upstream fragment has no no_shuffle dispatcher record for the backfill fragment id.","commonSituations":"MV built on a source undergoing backfill with a shuffled (e.g. hash) dispatcher instead of no_shuffle; fragments recreated by ALTER while backfill resolution runs.","solutions":["Ensure the upstream fragment dispatches with no_shuffle to the backfill fragment","Re-create the MV/source so the planner emits the required 1:1 mapping","Compare the logged actor_no_shuffle map against expected fragment ids","Upgrade RisingWave if the planner violates the source-backfill topology contract"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// check every backfill fragment has a 1:1 no_shuffle upstream mapping\nfor (frag, up) in &fragments {\n    assert!(actor_no_shuffle.get(up).map_or(false, |m| m.contains_key(frag)));\n}","typeGuard":null,"tryCatchPattern":"match resolve_backfill_splits(...) {\n    Err(e) if e.to_string().contains(\"one-on-one no_shuffle\") => {\n        // topology contract broken: recreate the MV/source\n    }\n    other => other?,\n}","preventionTips":["Do not introduce hash/shuffle dispatch between source backfill and upstream","Regenerate plans after ALTER operations before resuming backfill"],"tags":["rust","meta","source-backfill","dispatcher"],"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"}