{"record":{"id":"1e7e2a82a54a1506","repo":"risingwavelabs/risingwave","slug":"no-workers-to-assign-assignment-is-meaningless","errorCode":null,"errorMessage":"no workers to assign; assignment is meaningless","messagePattern":"no workers to assign; assignment is meaningless","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/stream/stream_graph/assignment.rs","lineNumber":749,"sourceCode":"        C: Ord + Hash + Eq + Clone + Debug,\n    {\n        let synthetic = (0..actor_count).collect::<Vec<_>>();\n        vec_len_map(self.assign_actors(workers, &synthetic))\n    }\n\n    /// Hierarchical assignment: Actors → Workers → `VNodes` → Actors.\n    pub fn assign_hierarchical<W, A, V>(\n        &self,\n        workers: &BTreeMap<W, NonZeroUsize>,\n        actors: &[A],\n        vnodes: &[V],\n    ) -> Result<BTreeMap<W, BTreeMap<A, Vec<V>>>>\n    where\n        W: Ord + Hash + Eq + Clone + Debug,\n        A: Ord + Hash + Eq + Copy + Debug,\n        V: Hash + Eq + Copy + Debug,\n    {\n        ensure!(\n            !workers.is_empty(),\n            \"no workers to assign; assignment is meaningless\"\n        );\n        ensure!(\n            !actors.is_empty(),\n            \"no actors to assign; assignment is meaningless\"\n        );\n        ensure!(\n            !vnodes.is_empty(),\n            \"no vnodes to assign; assignment is meaningless\"\n        );\n        ensure!(\n            vnodes.len() >= actors.len(),\n            \"not enough vnodes ({}) for actors ({}); each actor needs at least one vnode\",\n            vnodes.len(),\n            actors.len()\n        );\n","sourceCodeStart":731,"sourceCodeEnd":767,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/stream/stream_graph/assignment.rs#L731-L767","documentation":"The inner `assign_hierarchical` entry validates via `ensure!` that the worker list is non-empty; with zero workers there is nothing to assign actors/vnodes to, so the operation is refused. This is a precondition guard for the scheduling algorithm.","triggerScenarios":"Calling the assignment routine (assignment.rs:749) with an empty `workers` collection — e.g. when the cluster reports no schedulable compute nodes.","commonSituations":"All compute nodes down or not yet registered when a streaming job is scheduled; misconfigured cluster address list resulting in zero workers; tests invoking the assignment API with empty worker lists.","solutions":["Start/register at least one compute node before creating or rescheduling streaming jobs.","Check worker registration in the meta service and cluster config (worker nodes addresses).","In callers/tests, validate the worker list is non-empty before invoking assignment."],"exampleFix":"// before\nlet plan = assign_hierarchical(&[], &actors, &vnodes, strategy)?;\n// after\nanyhow::ensure!(!workers.is_empty(), \"no live compute workers; cannot assign actors\");\nlet plan = assign_hierarchical(&workers, &actors, &vnodes, strategy)?;","handlingStrategy":"validation","validationCode":"// Rust, before scheduling\nif workers.is_empty() {\n    anyhow::bail!(\"no live compute nodes registered; cannot schedule\");\n}","typeGuard":"fn has_live_workers(workers: &[WorkerId]) -> bool { !workers.is_empty() }","tryCatchPattern":"match assign_hierarchical(&workers, &actors, &vnodes, strategy) {\n    Ok(m) => m,\n    Err(e) if e.to_string().contains(\"no workers\") => {\n        // wait for workers and retry scheduling\n        retry_with_backoff(|| schedule_job(job))\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Verify compute node registration/health before creating streaming jobs.","Monitor worker liveness so scheduling never runs against an empty cluster.","In tests, seed at least one fake worker before assignment."],"tags":["assignment","workers","meta","empty-input"],"backgroundTag":"empty-required-field","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"}