{"record":{"id":"cadc4dcd56c70d33","repo":"risingwavelabs/risingwave","slug":"conflicting-reschedule-policies-for-fragments-in-t","errorCode":null,"errorMessage":"conflicting reschedule policies for fragments in the same no-shuffle ensemble: {:?}","messagePattern":"conflicting reschedule policies for fragments in the same no-shuffle ensemble: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/stream/scale.rs","lineNumber":390,"sourceCode":"            let entry_fragment_ids = ensemble.entry_fragments().collect_vec();\n\n            let desired_parallelism = match entry_fragment_ids\n                .iter()\n                .filter_map(|fragment_id| policy.get(fragment_id).cloned())\n                .dedup()\n                .collect_vec()\n                .as_slice()\n            {\n                [] => {\n                    bail_invalid_parameter!(\n                        \"none of the entry fragments {:?} were included in the reschedule request; \\\n                         provide at least one entry fragment id\",\n                        entry_fragment_ids\n                    );\n                }\n                [parallelism] => parallelism.clone(),\n                parallelisms => {\n                    bail!(\n                        \"conflicting reschedule policies for fragments in the same no-shuffle ensemble: {:?}\",\n                        parallelisms\n                    );\n                }\n            };\n\n            let fragments = Fragment::find()\n                .filter(fragment::Column::FragmentId.is_in(entry_fragment_ids))\n                .all(&txn)\n                .await?;\n\n            debug_assert!(\n                fragments\n                    .iter()\n                    .map(|fragment| fragment.parallelism.as_ref())\n                    .all_equal(),\n                \"entry fragments in the same ensemble should share the same parallelism\"\n            );","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/stream/scale.rs#L372-L408","documentation":"`reschedule_fragment_inplace` groups fragments into no-shuffle ensembles and requires every fragment in an ensemble to receive the same parallelism policy. When it collects the policies for an ensemble and finds more than one distinct value, it aborts with this error, because applying conflicting policies to fragments that must move together is undefined.","triggerScenarios":"Submitting a fragment-level reschedule (`ALTER ... SET FRAGMENT parallelism ...`) that specifies different fixed parallelism values for two or more fragments belonging to the same no-shuffle ensemble — e.g. fragment 2 -> fixed(4) and fragment 3 -> fixed(8) where both fragments are in one no-shuffle group.","commonSituations":"Operators tuning individual fragment parallelisms without knowing which fragments share a no-shuffle ensemble; scripted reschedules that iterate fragments and set different values; job topology changes altering ensemble membership between attempts.","solutions":["Inspect the logged `parallelisms` to see the conflicting values and identify the no-shuffle ensemble involved.","Resubmit the reschedule specifying the same parallelism policy for all fragments in the ensemble.","Simplify to a job-level parallelism reschedule if per-fragment control is not required.","Use the ensemble's entry fragment id to set the policy once, which propagates to the whole ensemble."],"exampleFix":"// before: conflicting per-fragment policies in one ensemble\nALTER TABLE t SET FRAGMENT 2 PARALLELISM = 4;\nALTER TABLE t SET FRAGMENT 3 PARALLELISM = 8; // same no-shuffle ensemble\n// after\nALTER TABLE t SET FRAGMENT 2 PARALLELISM = 4;\nALTER TABLE t SET FRAGMENT 3 PARALLELISM = 4;","handlingStrategy":"validation","validationCode":"// group fragments by ensemble and assert a single policy per ensemble before submitting\nfor (ensemble, policies) in policies_by_ensemble {\n    if policies.iter().collect::<HashSet<_>>().len() > 1 {\n        return Err(format!(\"ensemble {ensemble:?} has conflicting policies\"));\n    }\n}","typeGuard":null,"tryCatchPattern":"match reschedule_fragment(job_id, policies).await {\n    Err(e) if e.to_string().contains(\"no-shuffle ensemble\") => {\n        // unify to one policy per ensemble and retry\n        reschedule_fragment(job_id, unified_policies).await?\n    }\n    r => r?,\n}","preventionTips":["Learn which fragments share a no-shuffle ensemble before setting per-fragment parallelism.","Set the policy via the ensemble's entry fragment id instead of individual fragments.","Prefer job-level parallelism reschedule when uniform scaling is acceptable."],"tags":["reschedule","fragment","no-shuffle"],"backgroundTag":"conflicting-config-options","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"}