risingwavelabs/risingwave · error

failed to fold constant

Error message

failed to fold constant

What it means

Arguments to `internal_get_channel_delta_stats` must be constants so they can be evaluated at plan time. If constant folding of the argument expression itself returns an error, that error is wrapped with the context `failed to fold constant`.

Solutions

  1. Replace the argument with a plain constant literal.
  2. Remove volatile or non-deterministic functions from the argument expression.
  3. Fix the inner fold error shown by the anyhow cause chain (e.g. overflow or division by zero).
  4. Precompute the value client-side and inline it as a literal.

Example fix

-- before
SELECT * FROM internal_get_channel_delta_stats(now()::bigint, 0);
-- after
SELECT * FROM internal_get_channel_delta_stats(1726000000, 0);
Defensive patterns

Strategy: validation

Validate before calling

-- Only pass literals, not expressions
SELECT * FROM internal_get_channel_delta_stats(1726000000, 0);

Try / catch

match expr_impl_to_u64_fn(expr) {
    Ok(v) => /* proceed */,
    Err(e) => eprintln!("arg fold failed: {e:#}"), // inspect cause chain
}

Prevention

When it happens

Trigger: `build_plan` calls `expr_impl_to_u64_fn` on an argument whose fold produces `Some(Err(err))` — e.g. the expression contains a volatile function, division by zero during folding, or a fold-time type error.

Common situations: Passing expressions that reference columns or volatile functions (`now()`), or arithmetic that fails during evaluation (overflow, division by zero).

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


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

Appendix: source

Thrown at src/frontend/src/optimizer/rule/table_function_to_internal_get_channel_delta_stats.rs:55

        Some(Ok(value)) => {
            let Some(scalar) = value else {
                return Ok(None);
            };
            match scalar {
                ScalarImpl::Int64(value) => {
                    if value < 0 {
                        Err(anyhow::anyhow!(
                            "time parameter cannot be negative, got {}",
                            value
                        ))
                    } else {
                        Ok(Some(value as u64))
                    }
                }
                _ => Err(anyhow::anyhow!("expected int64, got {:?}", scalar)),
            }
        }
        Some(Err(err)) => Err(anyhow!(err).context("failed to fold constant")),
        None => Err(anyhow::anyhow!("expression must be a constant value")),
    }
}

/// Transform the `internal_get_channel_delta_stats()` table function
/// into a plan graph which will return channel statistics from the dashboard API.
/// It will return channel stats with `upstream_fragment_id` and `downstream_fragment_id` as primary key.
pub struct TableFunctionToInternalGetChannelDeltaStatsRule {}
impl FallibleRule<Logical> for TableFunctionToInternalGetChannelDeltaStatsRule {
    fn apply(&self, plan: PlanRef) -> ApplyResult<PlanRef> {
        let logical_table_function: &LogicalTableFunction = plan.as_logical_table_function()?;
        if logical_table_function.table_function().function_type
            != TableFunctionType::InternalGetChannelDeltaStats
        {
            return ApplyResult::NotApplicable;
        }
        let plan = Self::build_plan(plan.ctx(), logical_table_function.table_function())?;
        ApplyResult::Ok(plan)

View on GitHub (pinned to 6469eb736d)