{"record":{"id":"55519049a83fa7c9","repo":"risingwavelabs/risingwave","slug":"gap-interval-expression-returned-null-555190","errorCode":null,"errorMessage":"Gap interval expression returned null","messagePattern":"Gap interval expression returned null","errorType":"validation","errorClass":"StreamExecutorError","httpStatus":null,"severity":"error","filePath":"src/stream/src/executor/gap_fill.rs","lineNumber":561,"sourceCode":"            gap_interval,\n            high_gap_fill_amplification_threshold,\n            ctx,\n            input,\n            metrics,\n        } = *self;\n\n        let mut input = input.execute();\n\n        let barrier = expect_first_barrier(&mut input).await?;\n        let first_epoch = barrier.epoch;\n        yield Message::Barrier(barrier);\n        managed_state.init_epoch(first_epoch).await?;\n\n        // Calculate and validate gap interval once at initialization\n        let dummy_row = OwnedRow::new(vec![]);\n        let interval_datum = gap_interval.eval_row_infallible(&dummy_row).await;\n        let interval = interval_datum\n            .ok_or_else(|| anyhow::anyhow!(\"Gap interval expression returned null\"))?\n            .into_interval();\n\n        if interval <= Interval::from_month_day_usec(0, 0, 0) {\n            Err(anyhow::anyhow!(\"Gap interval must be positive\"))?;\n        }\n        let generation_context = GapFillGenerationContext {\n            metrics: &metrics,\n            high_amplification_threshold: high_gap_fill_amplification_threshold,\n            actor_ctx: &ctx,\n        };\n\n        let partition_by_indices = managed_state.partition_by_indices.clone();\n        let pointer_key_indices = managed_state.pointer_key_indices.clone();\n        // Interpolation re-slopes every fill, so a changed anchor changes all of them; only\n        // LOCF/NULL fills can be reused by the diff.\n        let has_interpolate = fill_columns\n            .values()\n            .any(|strategy| matches!(strategy, FillStrategy::Interpolate));","sourceCodeStart":543,"sourceCodeEnd":579,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/executor/gap_fill.rs#L543-L579","documentation":"The gap-fill executor evaluates the GAP interval expression once at initialization against an empty dummy row (the interval must be constant). If the expression evaluates to NULL, `execute_inner` returns this anyhow error because there is no valid gap width to drive the filling logic.","triggerScenarios":"A `GAP FILL` query where the GAP expression (e.g. `GAP NULL::INTERVAL`, a column reference that is NULL, or an expression evaluating to NULL under constant folding) yields a NULL datum at src/stream/src/executor/gap_fill.rs:561.","commonSituations":"Users parameterizing the gap via a nullable column or a subquery instead of a literal; mis-typed expressions that constant-fold to NULL.","solutions":["Replace the GAP expression with a non-null constant INTERVAL literal, e.g. `GAP INTERVAL '1 minute'`.","If the gap is computed by an expression, wrap it with COALESCE to a default: `GAP COALESCE(expr, INTERVAL '1 minute')`.","Verify the referenced column/parameter is not NULL at the time the MV is created."],"exampleFix":"// before\nSELECT GAP FILL(ts, gap_col) FROM t GROUP BY ts;\n// after\nSELECT GAP FILL(ts, INTERVAL '1 minute') FROM t GROUP BY ts;","handlingStrategy":"validation","validationCode":"-- Validate the gap expression is non-null before creating the MV:\nSELECT COALESCE(gap_expr, INTERVAL '1 minute') IS NOT NULL AS ok;\n-- Prefer a literal: GAP INTERVAL '1 minute'","typeGuard":null,"tryCatchPattern":"match gap_fill_mv_creation {\n    Err(e) if e.to_string().contains(\"Gap interval expression returned null\") => {\n        // re-create with a constant non-null INTERVAL\n    }\n    other => other?,\n}","preventionTips":["Use a constant INTERVAL literal for GAP; do not reference nullable columns.","Wrap computed gap expressions in COALESCE(expr, default_interval).","Remember the gap is evaluated once at MV creation, so it must be non-null then."],"tags":["stream-executor","gap-fill","null-value","interval"],"backgroundTag":"null-argument","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}