{"record":{"id":"d87ab14f55ba73fc","repo":"risingwavelabs/risingwave","slug":"actor-count-exceeds-vnode-count","errorCode":null,"errorMessage":"actor count ({}) exceeds vnode count ({})","messagePattern":"actor count \\((.+?)\\) exceeds vnode count \\((.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/stream/stream_graph/assignment.rs","lineNumber":406,"sourceCode":"    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,\n    };\n\n    // Distribute actors across workers based on their weight\n    let actor_to_worker: BTreeMap<W, Vec<A>> =\n        assign_items_weighted_with_scale_fn(workers, actors, salt, actor_capacity_fn);\n\n    // Build unit-weight map for active workers (those with assigned actors)\n    let mut active_worker_weights: BTreeMap<W, NonZeroUsize> = BTreeMap::new();\n","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/stream/stream_graph/assignment.rs#L388-L424","documentation":"`assign_hierarchical` validates that the number of actors does not exceed the number of virtual nodes, since every actor needs at least one vnode. When `actors.len() > virtual_nodes.len()`, balanced per-actor assignment is impossible and the function returns this descriptive error.","triggerScenarios":"Calling `assign_hierarchical` (assignment.rs:406) with more actor ids than vnode ids; test `error_when_more_actors_than_vnodes` exercises this.","commonSituations":"Manually constructing a tiny vnode set (e.g. 2 vnodes) while creating more actors (e.g. 4-way parallelism); test/tooling misuse of the generic API; a vnode-count override below the fragment's parallelism.","solutions":["Increase the vnode count to at least the actor count (RisingWave default is 256).","Reduce fragment parallelism so actors.len() <= vnodes.len().","When calling the API directly, always derive vnode count from the same config as parallelism instead of hardcoding."],"exampleFix":"// before\nlet vnodes: Vec<u32> = (0..2).collect();\nlet mapping = assign_hierarchical(&workers, &actors, &vnodes, strategy)?; // 4 actors\n// after\nlet vnodes: Vec<u32> = (0..256).collect();\nlet mapping = assign_hierarchical(&workers, &actors, &vnodes, strategy)?;","handlingStrategy":"validation","validationCode":"// Rust, before calling assignment\nif actors.len() > vnodes.len() {\n    anyhow::bail!(\"need at least {} vnodes, have {}\", actors.len(), vnodes.len());\n}","typeGuard":null,"tryCatchPattern":"match assign_hierarchical(&workers, &actors, &vnodes, strategy) {\n    Ok(m) => m,\n    Err(e) if e.to_string().contains(\"exceeds vnode count\") => {\n        Err(anyhow!(\"increase vnode count or reduce parallelism: {e:#}\"))\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Keep vnode count >= parallelism (default 256 covers realistic parallelism).","Do not shrink vnode sets in tests below the actor count.","Derive vnode count from the same config source as parallelism."],"tags":["assignment","meta","vnode","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}