{"record":{"id":"a8ac186b1d2c4e3f","repo":"risingwavelabs/risingwave","slug":"no-actors-to-assign","errorCode":null,"errorMessage":"no actors to assign","messagePattern":"no actors to assign","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/stream/stream_graph/assignment.rs","lineNumber":397,"sourceCode":"///    - For each worker, take its vnode list and assign them to actors in simple round-robin:\n///      iterate vnodes in order, dispatching index `% actor_list.len()`.\n///    - Collect into final `BTreeMap<W, BTreeMap<A, Vec<V>>>`.\npub fn assign_hierarchical<W, A, V, S>(\n    workers: &BTreeMap<W, NonZeroUsize>,\n    actors: &[A],\n    virtual_nodes: &[V],\n    salt: S,\n    actor_capacity_mode: CapacityMode,\n    balanced_by: BalancedBy,\n) -> anyhow::Result<BTreeMap<W, BTreeMap<A, Vec<V>>>>\nwhere\n    W: Ord + Hash + Eq + Clone + Debug,\n    A: Ord + Hash + Eq + Copy + Clone + Debug,\n    V: Hash + Eq + Copy + Clone + Debug,\n    S: Hash + Copy,\n{\n    if actors.is_empty() {\n        return Err(anyhow!(\"no actors to assign\"));\n    }\n\n    if virtual_nodes.is_empty() {\n        return Err(anyhow!(\"no vnodes to assign\"));\n    }\n\n    // Validate input: ensure vnode count can cover all actors\n    if actors.len() > virtual_nodes.len() {\n        return Err(anyhow!(\n            \"actor count ({}) exceeds vnode count ({})\",\n            actors.len(),\n            virtual_nodes.len()\n        ));\n    }\n\n    let actor_capacity_fn = match actor_capacity_mode {\n        CapacityMode::Weighted => weighted_scale,\n        CapacityMode::Unbounded => unbounded_scale,","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/stream/stream_graph/assignment.rs#L379-L415","documentation":"The generic `assign_hierarchical` worker/actor/vnode assignment function requires at least one actor to distribute; an empty actor list makes the assignment meaningless. It fails fast at the top of the function before any distribution work.","triggerScenarios":"Calling `assign_hierarchical` (assignment.rs:397) with `actors.is_empty() == true`; tests `error_on_empty_actors` exercise this directly.","commonSituations":"Building/assigning a stream fragment whose actor set was not generated (e.g. a degenerate fragment with zero parallelism); calling the assignment API in tests or tools with an empty actor vector; upstream bug that filtered out all actors before assignment.","solutions":["Ensure the fragment graph has generated actors (parallelism >= 1) before calling assignment.","Guard the caller: skip assignment or return a domain error when `actors.is_empty()`.","Check why upstream rewrite produced zero actors for the fragment (e.g. disabled fragments) and fix plan generation."],"exampleFix":"// before\nlet mapping = assign_hierarchical(&workers, &[], &vnodes, strategy)?;\n// after\nif actors.is_empty() {\n    anyhow::bail!(\"fragment has no actors to assign\");\n}\nlet mapping = assign_hierarchical(&workers, &actors, &vnodes, strategy)?;","handlingStrategy":"validation","validationCode":"// Rust, before calling assignment\nif actors.is_empty() {\n    anyhow::bail!(\"refusing to assign: actor list is empty\");\n}","typeGuard":"fn non_empty<'a, T>(xs: &'a [T]) -> Option<&'a [T]> {\n    if xs.is_empty() { None } else { Some(xs) }\n}","tryCatchPattern":"match assign_hierarchical(&workers, &actors, &vnodes, strategy) {\n    Ok(mapping) => mapping,\n    Err(e) if e.to_string().contains(\"no actors to assign\") => {\n        tracing::warn!(\"skipping assignment: no actors generated\");\n        BTreeMap::new()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always generate actors (parallelism >= 1) before scheduling.","Validate fragment outputs in plan generation tests.","Filter degenerate zero-actor fragments upstream with explicit errors."],"tags":["assignment","meta","validation","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"}