risingwavelabs/risingwave · error
GetChannelDeltaStatsExecutor should have no child!
Error message
GetChannelDeltaStatsExecutor should have no child!
What it means
During `deserialize_stream_chunk`, the number of decoded operations exceeded the `size_bound` the caller supplied for the chunk. `size_bound` caps how many rows a serialized chunk may contain so a maliciously or erroneously oversized payload cannot blow up memory; exceeding it aborts the decode.
Source
Thrown at src/batch/executors/src/executor/get_channel_delta_stats.rs:137
let columns: Vec<_> = array_builders
.into_iter()
.map(|b| b.finish().into())
.collect();
let chunk = DataChunk::new(columns, rows.len());
yield chunk;
}
}
}
impl BoxedExecutorBuilder for GetChannelDeltaStatsExecutor {
async fn new_boxed_executor(
source: &ExecutorBuilder<'_>,
inputs: Vec<BoxedExecutor>,
) -> Result<BoxedExecutor> {
ensure!(
inputs.is_empty(),
"GetChannelDeltaStatsExecutor should have no child!"
);
let get_channel_delta_stats_node = try_match_expand!(
source.plan_node().get_node_body().unwrap(),
NodeBody::GetChannelDeltaStats
)?;
// Create a schema for channel stats
// This should match the expected schema from table_function.rs
let fields = vec![
Field::new("upstream_fragment_id", DataType::Int32),
Field::new("downstream_fragment_id", DataType::Int32),
Field::new("backpressure_rate", DataType::Float64),
Field::new("recv_throughput", DataType::Float64),
Field::new("send_throughput", DataType::Float64),
];
View on GitHub (pinned to 6469eb736d)
Solutions
- Ensure the write side never serializes more rows per chunk than the configured `size_bound`.
- Fix the read range selection so `[start_seq_id, end_seq_id)` covers at most one chunk's rows.
- Increase size_bound if the workload legitimately needs larger chunks (and align it with writer settings).
- Inspect the seq-id range and stored rows to detect duplicated or miswritten entries.
Defensive patterns
Strategy: validation
Validate before calling
// rust
// estimate ops in the requested range before decoding
let est = reader.estimate_row_count(start_seq_id, end_seq_id);
anyhow::ensure!(est <= size_bound, "range [{}, {}) holds {} ops > size_bound {}", start_seq_id, end_seq_id, est, size_bound); Prevention
- Enforce size_bound on the write side when serializing chunks.
- Keep reader and writer size_bound settings in sync.
- Never extend end_seq_id past one chunk's worth of rows.
When it happens
Trigger: Decoding a `[start_seq_id, end_seq_id)` range whose stored `LogStoreOp::Row` entries total more than `size_bound` ops (checked after each `ops.push(op)`). Thrown at serde.rs:472.
Common situations: Read range spanning more rows than estimated (e.g. start/end seq ids computed from a bad row-count estimate); rows written without respecting the chunk size bound; replaying a range twice because seq-id tracking desynced.
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
- Iceberg metadata type is unspecified
- Iceberg metadata scan should not have input executors
- Iceberg metadata scan received a non-Iceberg connector
- file_scan_tasks must be Some
- Chunk size can't be zero!
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/1d93130f34448026.
Report an issue: GitHub.