risingwavelabs/risingwave · error · ExprError

multiple errors: {1}

Error message

multiple errors:
{1}

What it means

ExprError::Multiple wraps an array of per-row error values accumulated during batch (vectorized) expression evaluation. When several rows fail, the library collects the error strings into a MultiExprError and reports them together with the offending ArrayRef.

Source

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

pub struct ContextUnavailable(&'static str);

impl ContextUnavailable {
    pub fn new(field: &'static str) -> Self {
        Self(field)
    }
}

impl From<ContextUnavailable> for ExprError {
    fn from(e: ContextUnavailable) -> Self {
        ExprError::Context(e.0)
    }
}

/// The error type for expression operations.
#[derive(Error, ReportDebug)]
pub enum ExprError {
    /// A collection of multiple errors in batch evaluation.
    #[error("multiple errors:\n{1}")]
    Multiple(ArrayRef, MultiExprError),

    // Ideally "Unsupported" errors are caught by frontend. But when the match arms between
    // frontend and backend are inconsistent, we do not panic with `unreachable!`.
    #[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,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Read the inner error strings in the message to find which rows/values failed
  2. Clean or filter invalid input rows before evaluation
  3. Use per-row fallbacks (e.g. try_cast, nullif) to avoid hard failures
  4. Add data quality checks upstream in the ingestion pipeline

Example fix

// before
SELECT col::int FROM t; -- multiple invalid rows
// after
SELECT try_cast(col as int) FROM t;
Defensive patterns

Strategy: try-catch

Validate before calling

// validate inputs before batch evaluation
let ok = rows.iter().all(|r| can_cast(r, target_type));

Try / catch

match expr.eval(batch).await {
    Err(e) if matches!(e.root_cause(), _) || e.to_string().starts_with("multiple errors:") => {
        // parse inner per-row errors, fall back to row-wise evaluation
    }
    other => other?,
}

Prevention

When it happens

Trigger: Batch evaluation of an expression (e.g. cast, div) where multiple rows produce errors; the evaluator aggregates row errors into MultiExprError and constructs ExprError::Multiple.

Common situations: Casting a column with several invalid values; division by zero in multiple rows of a batch query; running queries over materialized views containing dirty data.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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