risingwavelabs/risingwave · error · ExprError
not a constant
Error message
not a constant
What it means
ExprError::NotConstant is thrown when code that requires a constant (literal, foldable) expression receives a non-constant one. Certain APIs in the expression crate — e.g. extracting literal values for planning or constant folding — only accept expressions whose value is known at planning time.
Solutions
- Constant-fold the expression before extracting it (run the constant-folding pass).
- Handle the non-constant case explicitly instead of expecting a literal.
- If the value must be known statically, provide it as a literal parameter rather than a runtime expression.
Example fix
// before let v = expr.as_literal().ok_or(ExprError::NotConstant)?; // expr is a column ref // after let folded = constant_fold(expr); let v = folded.as_literal().ok_or_else(|| ExprError::NotConstant)?;
Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: check constness before calling constant-only APIs
if expr.is_const_foldable() { extract_const(expr)?; } else { /* dynamic path */ } Type guard
fn as_const(expr: &ExprImpl) -> Option<Literal> {
constant_fold(expr.clone()).as_literal()
} Prevention
- Run constant-folding before any constant-extraction API.
- Never assume a literal after a rewrite; re-check foldability.
- Route non-constant expressions to the dynamic evaluation path.
When it happens
Trigger: Calling constant-extraction APIs (match on literal variants, `eval_const`-style helpers) with a column reference, volatile function, or any expression not folded to a literal during planning.
Common situations: Optimizer/planner passes assuming a literal after partial constant folding, custom expression rewrites passing dynamic expressions into constant-only APIs.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- children expression must not be empty for constant lookup…
- expression must be a constant value
- failed to fold constant
- GenerateSeriesExecutor should not have child!
- Row sequential scan should not have input executor!
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/3445132a186fba8f.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/core/src/error.rs:99
#[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,
#[error("too few arguments for format()")]
TooFewArguments,
#[error(
"null value in column \"{col_name}\" of relation \"{table_name}\" violates not-null constraint"
)]
NotNullViolation {
col_name: Box<str>,
table_name: Box<str>,
},View on GitHub (pinned to 6469eb736d)