risingwavelabs/risingwave · error
cardinality > 0
Error message
cardinality > 0
What it means
Thrown in the VALUES executor's `execute_inner` when the declared schema has zero columns. A VALUES (constant relation) must emit at least one column; a zero-column schema would make the one-row dummy chunk meaningless and downstream expression evaluation impossible.
Solutions
- Fix the planner so the constant relation always has at least one column (e.g. add a dummy unit column).
- Check the SQL that produced the plan; avoid statements yielding an empty column set.
- Ensure frontend and stream versions match; older frontends may emit degenerate schemas.
Example fix
-- before SELECT; -- after SELECT 1; -- or ensure the VALUES clause lists at least one column
Defensive patterns
Strategy: validation
Validate before calling
// before constructing ValuesExecutor
if schema.is_empty() {
// add a dummy unit column or reject the plan early
} Type guard
fn has_columns(schema: &Schema) -> bool { !schema.fields.is_empty() } Prevention
- Never plan constant relations with zero columns; add a dummy column in the frontend
- Add planner tests for degenerate SELECT/VALUES shapes
- Check schema before feeding constant relations into the stream engine
When it happens
Trigger: Creating a `ValuesExecutor` whose `schema.len() == 0`, e.g. planning a `VALUES` clause or a query that resolves to a constant relation with an empty column list.
Common situations: Frontend planner bugs producing an empty projection for a constant relation; SQL like `SELECT;` or a `VALUES` with an empty field list reaching the stream engine; misconfigured internal constant-relations used for system catalogs.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- compaction resolver PK column missing column_desc
- MATCH_RECOGNIZE ORDER BY column
- {0}
- {0}
- a stream has reached the end but some other stream has not…
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/be7d6ef0fa71481f.
Report an issue: GitHub.
Appendix: source
Thrown at src/stream/src/executor/values.rs:92
let paused_on_startup = barrier.is_pause_on_startup();
yield Message::Barrier(barrier);
// If it's failover, do not evaluate rows (assume they have been yielded)
if emit {
if paused_on_startup {
// Wait for the data stream to be resumed before yielding the chunks.
while let Some(barrier) = barrier_receiver.recv().await {
let is_resume = barrier.is_resume();
yield Message::Barrier(barrier);
if is_resume {
break;
}
}
}
let cardinality = schema.len();
ensure!(cardinality > 0);
while !rows.is_empty() {
// We need a one row chunk rather than an empty chunk because constant
// expression's eval result is same size as input chunk
// cardinality.
let one_row_chunk = DataChunk::new_dummy(1);
let chunk_size = DEFAULT_CHUNK_SIZE.min(rows.len());
let mut array_builders = schema.create_array_builders(chunk_size);
for row in rows.by_ref().take(chunk_size) {
for (expr, builder) in row.into_iter().zip_eq_fast(&mut array_builders) {
let out = expr.eval_infallible(&one_row_chunk).await;
builder.append_array(&out);
}
}
let columns: Vec<_> = array_builders
.into_iter()
.map(|b| b.finish().into())View on GitHub (pinned to 6469eb736d)