risingwavelabs/risingwave · critical

reserved memory ({}) >= total memory ({}).

Error message

reserved memory ({}) >= total memory ({}).

What it means

reserve_memory_bytes panics when the reserved memory amount (after being clamped up to at least MIN_SYSTEM_RESERVED_MEMORY_MB) is greater than or equal to the configured total_memory_bytes. This invariant guarantees there is actual memory left for user workloads; if the reservation swallows all memory, the configuration is invalid.

Source

Thrown at src/compute/src/memory/config.rs:70

pub fn reserve_memory_bytes(opts: &ComputeNodeOpts) -> (usize, usize) {
    if opts.total_memory_bytes < MIN_COMPUTE_MEMORY_MB << 20 {
        panic!(
            "The total memory size ({}) is too small. It must be at least {} MB.",
            convert(opts.total_memory_bytes as _),
            MIN_COMPUTE_MEMORY_MB
        );
    }

    // If `reserved_memory_bytes` is not set, calculate total_memory_bytes based on gradient reserve memory proportion.
    let reserved = opts
        .reserved_memory_bytes
        .unwrap_or_else(|| gradient_reserve_memory_bytes(opts.total_memory_bytes));

    // Should have at least `MIN_SYSTEM_RESERVED_MEMORY_MB` for reserved memory.
    let reserved = std::cmp::max(reserved, MIN_SYSTEM_RESERVED_MEMORY_MB << 20);

    if reserved >= opts.total_memory_bytes {
        panic!(
            "reserved memory ({}) >= total memory ({}).",
            convert(reserved as _),
            convert(opts.total_memory_bytes as _)
        );
    }

    (reserved, opts.total_memory_bytes - reserved)
}

/// Calculate the reserved memory based on the total memory size.
/// The reserved memory size is calculated based on the following gradient:
/// - 30% of the first 16GB
/// - 20% of the rest
pub fn gradient_reserve_memory_bytes(total_memory_bytes: usize) -> usize {
    let mut total_memory_bytes = total_memory_bytes;
    let mut reserved = 0;
    for i in 0..RESERVED_MEMORY_LEVELS.len() {
        let level_diff = if i == 0 {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Increase total_memory_bytes so it comfortably exceeds MIN_SYSTEM_RESERVED_MEMORY_MB (leaving room for workload memory).
  2. Lower the explicit reserved-memory option if one was set, letting the gradient-based default apply.
  3. Review the computed 'reserved' value in reserve_memory_bytes (src/compute/src/memory/config.rs:60-70) and size total memory as reserved + expected workload memory.

Example fix

// before
--total-memory-bytes 268435456 --reserved-memory-bytes 268435456  # reserved >= total
// after
--total-memory-bytes 2147483648  # let reservation be derived, leaving workload memory
Defensive patterns

Strategy: validation

Validate before calling

# Ensure total memory leaves room after the minimum system reservation
min_reserved_bytes = 512 * 1024 * 1024  # check MIN_SYSTEM_RESERVED_MEMORY_MB
total_bytes = 2147483648
assert total_bytes > min_reserved_bytes, 'total memory must exceed minimum system reservation'

Prevention

When it happens

Trigger: total_memory_bytes is only slightly above MIN_COMPUTE_MEMORY_MB while the gradient-based or explicit reservation, clamped to MIN_SYSTEM_RESERVED_MEMORY_MB, meets or exceeds it; setting an explicit reserved-bytes option larger than the total; running with a tiny container memory limit.

Common situations: Very small k8s memory limits (e.g. 256MB) where the minimum system reservation already covers everything; mismatched config where reserved memory was pinned high but total memory was lowered.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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