risingwavelabs/risingwave · critical

invalid parallelism

Error message

invalid parallelism

What it means

When registering a Frontend worker with no existing property record, the code builds a worker_property::ActiveModel and converts add_property.parallelism (unsigned) into the DB integer type with try_into().expect("invalid parallelism"). If parallelism cannot be converted (e.g. exceeds the target integer range), expect panics with this message — it is an unrecoverable invariant, not a returned error.

Source

Thrown at src/meta/src/controller/cluster.rs:701

                    Set(Some(add_property.resource_group.unwrap_or_else(|| {
                        tracing::warn!(
                            "resource_group is not set for worker {}, fallback to `default`",
                            worker.worker_id
                        );
                        DEFAULT_RESOURCE_GROUP.to_owned()
                    })));

                WorkerProperty::update(property).exec(&txn).await?;
                txn.commit().await?;
                self.update_worker_ttl(worker.worker_id, ttl)?;
                Ok(worker.worker_id)
            } else if worker.worker_type == WorkerType::Frontend && property.is_none() {
                let worker_property = worker_property::ActiveModel {
                    worker_id: Set(worker.worker_id),
                    parallelism: Set(add_property
                        .parallelism
                        .try_into()
                        .expect("invalid parallelism")),
                    is_streaming: Set(add_property.is_streaming),
                    is_serving: Set(add_property.is_serving),
                    is_unschedulable: Set(false),
                    internal_rpc_host_addr: Set(Some(add_property.internal_rpc_host_addr)),
                    resource_group: Set(None),
                    is_iceberg_compactor: Set(false),
                    resource: Set(Some((&resource).into())),
                    started_at: Set(Some(started_at as _)),
                };
                WorkerProperty::insert(worker_property).exec(&txn).await?;
                txn.commit().await?;
                self.update_worker_ttl(worker.worker_id, ttl)?;
                Ok(worker.worker_id)
            } else if worker.worker_type == WorkerType::Compactor {
                if let Some(property) = property {
                    let mut property: worker_property::ActiveModel = property.into();
                    property.is_iceberg_compactor = Set(add_property.is_iceberg_compactor);
                    property.internal_rpc_host_addr =

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Send a sane parallelism value in the add-node request (fits within i32).
  2. Ensure client and cluster use compatible protobuf versions so the parallelism field is decoded correctly.
  3. Replace the expect with validated/returned error handling in meta code if maintaining a fork.

Example fix

// before
parallelism: Set(add_property.parallelism.try_into().expect("invalid parallelism")),
// after
let parallelism: i32 = add_property.parallelism.try_into().map_err(|_| MetaError::invalid_parameter("parallelism out of range"))?;
parallelism: Set(parallelism),
Defensive patterns

Strategy: validation

Validate before calling

// Rust (client of AddWorker RPC)
fn valid_parallelism(p: u32) -> bool { p > 0 && p <= i32::MAX as u32 }
assert!(valid_parallelism(props.parallelism), "parallelism must fit i32");

Type guard

fn fits_i32(v: u32) -> Option<i32> { i32::try_from(v).ok() }

Try / catch

// This is a panic (expect), not an Err — guard at the boundary instead.
let p = i32::try_from(add_property.parallelism)
    .expect("invalid parallelism"); // only safe if you validated above

Prevention

When it happens

Trigger: ADD NODE / worker registration for a Frontend node whose reported parallelism cannot be represented in the storage type (e.g. > i32::MAX due to a malformed or hostile WorkerNode property).

Common situations: Misconfigured or buggy client sending absurd parallelism values in AddWorkerProperties; binary/protobuf version mismatch misinterpreting the field.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/7c47a43976805131. Report an issue: GitHub.