risingwavelabs/risingwave · error
actor count ({}) exceeds vnode count ({})
Error message
actor count ({}) exceeds vnode count ({}) What it means
`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.
Source
Thrown at src/meta/src/stream/stream_graph/assignment.rs:406
balanced_by: BalancedBy,
) -> anyhow::Result<BTreeMap<W, BTreeMap<A, Vec<V>>>>
where
W: Ord + Hash + Eq + Clone + Debug,
A: Ord + Hash + Eq + Copy + Clone + Debug,
V: Hash + Eq + Copy + Clone + Debug,
S: Hash + Copy,
{
if actors.is_empty() {
return Err(anyhow!("no actors to assign"));
}
if virtual_nodes.is_empty() {
return Err(anyhow!("no vnodes to assign"));
}
// Validate input: ensure vnode count can cover all actors
if actors.len() > virtual_nodes.len() {
return Err(anyhow!(
"actor count ({}) exceeds vnode count ({})",
actors.len(),
virtual_nodes.len()
));
}
let actor_capacity_fn = match actor_capacity_mode {
CapacityMode::Weighted => weighted_scale,
CapacityMode::Unbounded => unbounded_scale,
};
// Distribute actors across workers based on their weight
let actor_to_worker: BTreeMap<W, Vec<A>> =
assign_items_weighted_with_scale_fn(workers, actors, salt, actor_capacity_fn);
// Build unit-weight map for active workers (those with assigned actors)
let mut active_worker_weights: BTreeMap<W, NonZeroUsize> = BTreeMap::new();
View on GitHub (pinned to 6469eb736d)
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.
Example fix
// before let vnodes: Vec<u32> = (0..2).collect(); let mapping = assign_hierarchical(&workers, &actors, &vnodes, strategy)?; // 4 actors // after let vnodes: Vec<u32> = (0..256).collect(); let mapping = assign_hierarchical(&workers, &actors, &vnodes, strategy)?;
Defensive patterns
Strategy: validation
Validate before calling
// Rust, before calling assignment
if actors.len() > vnodes.len() {
anyhow::bail!("need at least {} vnodes, have {}", actors.len(), vnodes.len());
} Try / catch
match assign_hierarchical(&workers, &actors, &vnodes, strategy) {
Ok(m) => m,
Err(e) if e.to_string().contains("exceeds vnode count") => {
Err(anyhow!("increase vnode count or reduce parallelism: {e:#}"))
}
Err(e) => Err(e),
} Prevention
- 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.
When it happens
Trigger: Calling `assign_hierarchical` (assignment.rs:406) with more actor ids than vnode ids; test `error_when_more_actors_than_vnodes` exercises this.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- not enough vnodes ({}) for actors ({}); each actor needs at
- no actors to assign
- no vnodes to assign
- no actors to assign; assignment is meaningless
- no vnodes to assign; assignment is meaningless
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/d87ab14f55ba73fc.
Report an issue: GitHub.