risingwavelabs/risingwave · error · StreamExecutorError
Gap interval must be positive
Error message
Gap interval must be positive
What it means
After the gap interval is resolved (see the null check), the EOWC gap-fill executor validates that the interval is strictly greater than zero using `interval <= Interval::from_month_day_usec(0, 0, 0)`. A zero or negative gap interval would cause the fill loop to make no progress or behave nonsensically, so initialization fails fast with "Gap interval must be positive".
Solutions
- Set the gap interval to a strictly positive value, e.g. `INTERVAL '1 minute'`, and recreate the materialized view.
- If the interval comes from application code or a template, validate it is > 0 before generating the SQL.
- If zero gap is intended, remove the gap-fill option entirely instead of passing a zero interval.
- Double-check negative interval strings (`-INTERVAL ...`) and unary minus in generated SQL.
Example fix
// before WITH (gap_interval = INTERVAL '0 seconds') // after WITH (gap_interval = INTERVAL '1 minute')
Defensive patterns
Strategy: validation
Validate before calling
-- Validate the interval is strictly positive before use: SELECT INTERVAL '5 minutes' > INTERVAL '0' AS positive; -- must be true
Prevention
- Validate user-supplied gap intervals are > 0 in application code before generating SQL.
- Use omit-the-option rather than interval 0 to mean 'no gap fill'.
- Check templates for accidental unary minus on intervals.
When it happens
Trigger: Executing a gap-fill query whose constant gap interval evaluates to zero or negative — e.g., `INTERVAL '0 seconds'`, `INTERVAL '-5 minutes'`, or a negative computed literal that survives the constant evaluation.
Common situations: Templated/generated SQL where the interval parameter was substituted as 0 or a negative number; experimenting with gap fill and passing 0 to mean 'no gap' instead of omitting the option; a sign typo in an interval string.
Related errors
- Gap interval expression returned null
- AFTER MATCH SKIP TO FIRST/LAST missing its target variable
- Expected at most 1 clean_watermark_index per table, got
- Expression error
- MATCH_RECOGNIZE only supports the default ascending ORDER…
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/b470b60a83077798.
Report an issue: GitHub.
Appendix: source
Thrown at src/stream/src/executor/eowc/eowc_gap_fill.rs:370
} = self;
let mut input = input.execute();
let barrier = expect_first_barrier(&mut input).await?;
let first_epoch = barrier.epoch;
yield Message::Barrier(barrier);
this.prev_row_table.init_epoch(first_epoch).await?;
// Calculate and validate gap interval once at initialization
let dummy_row = OwnedRow::new(vec![]);
let interval_datum = this.gap_interval.eval_row_infallible(&dummy_row).await;
let interval = interval_datum
.ok_or_else(|| anyhow::anyhow!("Gap interval expression returned null"))?
.into_interval();
// Validate that gap interval is positive.
if interval <= Interval::from_month_day_usec(0, 0, 0) {
Err(anyhow::anyhow!("Gap interval must be positive"))?;
}
let mut vars = ExecutionVars {
staging_prev_rows: HashMap::new(),
};
#[for_await]
for msg in input {
match msg? {
// Drop the time watermark: a late anchor makes gap fill back-fill below it.
// PARTITION BY column watermarks (if any) pass through unchanged.
Message::Watermark(watermark)
if this.partition_by_indices.contains(&watermark.col_idx) =>
{
yield Message::Watermark(watermark);
}
Message::Watermark(_) => continue,
Message::Chunk(chunk) => {View on GitHub (pinned to 6469eb736d)