risingwavelabs/risingwave · error · ExprError

Division by zero

Error message

Division by zero

What it means

ExprError::DivisionByZero is thrown when an expression evaluation attempts to divide a numeric value by zero (or by a value that is effectively zero, e.g. numeric 0). The expression core detects the zero divisor at evaluation time and returns this error instead of panicking or producing an undefined result. It matches Postgres semantics where division by zero raises an error rather than returning NULL.

Source

Thrown at src/expr/core/src/error.rs:67

    #[error("Unsupported function: {0}")]
    UnsupportedFunction(String),

    #[error("Unsupported cast: {0} to {1}")]
    UnsupportedCast(DataType, DataType),

    #[error("Casting to {0} out of range")]
    CastOutOfRange(&'static str),

    #[error("Numeric out of range")]
    NumericOutOfRange,

    #[error("Numeric out of range: underflow")]
    NumericUnderflow,

    #[error("Numeric out of range: overflow")]
    NumericOverflow,

    #[error("Division by zero")]
    DivisionByZero,

    #[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,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Add an explicit zero check in SQL: `CASE WHEN denom = 0 THEN NULL ELSE num / denom END`.
  2. Use `NULLIF(denom, 0)` as the denominator: `num / NULLIF(denom, 0)` so the result becomes NULL instead of erroring.
  3. If this happens inside a streaming pipeline, guard the denominator expression upstream in the materialized view definition.

Example fix

// before
CREATE MATERIALIZED VIEW mv AS SELECT clicks / impressions AS ctr FROM stats;
// after
CREATE MATERIALIZED VIEW mv AS SELECT clicks / NULLIF(impressions, 0) AS ctr FROM stats;
Defensive patterns

Strategy: validation

Validate before calling

// SQL-level guard before division
SELECT num / NULLIF(denom, 0) AS ratio FROM t;

Try / catch

// Rust caller
match result {
    Err(e) if matches!(e.downcast_ref::<ExprError>(), Some(ExprError::DivisionByZero)) => Some(f64::NAN), // or None
    other => other.ok(),
}

Prevention

When it happens

Trigger: Evaluating a `/` expression (integer, decimal/numeric, or floating point depending on type semantics) where the right-hand operand evaluates to 0; also via batch/stream expression execution of user SQL like `SELECT 1/0` or `sum(x)/count(x)` when count is 0.

Common situations: Aggregate-derived denominators that can be zero (ratio of counts), user-written queries with literal 0 denominators, upstream data changes that make previously non-zero columns zero, percentile/average computations over empty windows.

Related errors


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