risingwavelabs/risingwave · error · ExprError
More than one row returned by {0} used as an expression
Error message
More than one row returned by {0} used as an expression What it means
ExprError::MaxOneRow(&'static str) is thrown when a scalar subquery (or similar row-yielding expression) returns more than one row. The message interpolates what construct ('{0}') was used as an expression, mirroring Postgres's 'more than one row returned by a subquery used as an expression'. A scalar context can only consume a single row.
Source
Thrown at src/expr/core/src/error.rs:88
#[error("Parse error: {0}")]
// TODO(error-handling): should prefer use error types than strings.
Parse(Box<str>),
#[error("Invalid parameter {name}: {reason}")]
// TODO(error-handling): should prefer use error types than strings.
InvalidParam {
name: &'static str,
reason: Box<str>,
},
#[error("Array error: {0}")]
Array(
#[from]
#[backtrace]
ArrayError,
),
#[error("More than one row returned by {0} used as an expression")]
MaxOneRow(&'static str),
/// TODO: deprecate in favor of `Function`
#[error(transparent)]
Internal(
#[from]
#[backtrace]
anyhow::Error,
),
#[error("not a constant")]
NotConstant,
#[error("Context {0} not found")]
Context(&'static str),
#[error("field name must not be null")]
FieldNameNull,View on GitHub (pinned to 6469eb736d)
Solutions
- Add `LIMIT 1` if any single row is acceptable.
- Add `DISTINCT` when duplicates are spurious.
- Tighten the subquery's WHERE clause (or add a unique constraint) so it provably returns at most one row.
Example fix
// before SELECT * FROM a WHERE id = (SELECT a_id FROM b WHERE flag = true); // after SELECT * FROM a WHERE id = (SELECT a_id FROM b WHERE flag = true LIMIT 1);
Defensive patterns
Strategy: validation
Validate before calling
-- ensure scalar subquery yields at most one row SELECT * FROM a WHERE id = (SELECT DISTINCT a_id FROM b WHERE flag = true LIMIT 1);
Try / catch
// Postgres-compatible error; catch and rewrite with LIMIT at retry
if err.to_string().contains("More than one row returned") {
return run(query_with_limit_1);
} Prevention
- Add LIMIT 1 or DISTINCT to every scalar subquery unless uniqueness is guaranteed.
- Back scalar-subquery columns with unique constraints.
- Watch for fan-out joins upstream that break single-row assumptions.
When it happens
Trigger: A scalar subquery on the right side of `=`, in a SELECT list, or in a SET clause produces 2+ rows, e.g. `SELECT x = (SELECT id FROM t WHERE k = 1)` where the WHERE clause matches multiple rows.
Common situations: Subqueries written against a uniqueness assumption that no longer holds after data changes, missing DISTINCT/LIMIT, join fan-out in upstream tables making lookups non-unique.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Scalar subquery might produce more than one row.
- subquery must return only one column
- Scalar subquery produced more than one row.
- missing FORMAT ... ENCODE ...
- Invalid order key: empty item in `{expr}`
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/8d3edf6308fd8b09.
Report an issue: GitHub.