{"record":{"id":"c8973ec80077a76c","repo":"risingwavelabs/risingwave","slug":"time-column-should-be-timestamp-or-timestamptz-c8973e","errorCode":null,"errorMessage":"Time column should be Timestamp or Timestamptz","messagePattern":"Time column should be Timestamp or Timestamptz","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/stream/src/executor/gap_fill.rs","lineNumber":394,"sourceCode":"                    Some(t) => t,\n                    None => break,\n                };\n                continue;\n            }\n            let mut new_row_data = Vec::with_capacity(prev_row.len());\n\n            for col_idx in 0..prev_row.len() {\n                let datum = if col_idx == time_column_index {\n                    // Time column: use the incremented timestamp\n                    let fill_time_scalar = match prev_time_scalar {\n                        ScalarRefImpl::Timestamp(_) => ScalarImpl::Timestamp(fill_time),\n                        ScalarRefImpl::Timestamptz(_) => {\n                            let micros = fill_time.0.and_utc().timestamp_micros();\n                            ScalarImpl::Timestamptz(\n                                risingwave_common::types::Timestamptz::from_micros_uncheck(micros),\n                            )\n                        }\n                        _ => unreachable!(\"Time column should be Timestamp or Timestamptz\"),\n                    };\n                    Some(fill_time_scalar)\n                } else if partition_by_indices.contains(&col_idx) {\n                    // Gap-filled rows must stay in the same partition as the surrounding anchors.\n                    prev_row.datum_at(col_idx).to_owned_datum()\n                } else if let Some(strategy) = fill_columns.get(&col_idx) {\n                    // Apply the fill strategy for this column\n                    match strategy {\n                        FillStrategy::Locf => prev_row.datum_at(col_idx).to_owned_datum(),\n                        FillStrategy::Null => None,\n                        FillStrategy::Interpolate => {\n                            // Apply interpolation step and update cumulative value\n                            if let Some(step) = &interpolation_steps[col_idx] {\n                                apply_interpolation_step(&mut interpolation_states[col_idx], step);\n                                interpolation_states[col_idx].clone()\n                            } else {\n                                // If interpolation step is None, fill with NULL\n                                None","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/executor/gap_fill.rs#L376-L412","documentation":"In gap-fill (GAP FILL / RANGE window aggregation), the time column of each row is converted to the fill timestamp; only `Timestamp` and `Timestamptz` scalar types are supported. When the time column holds another type, the `unreachable!` panics with this message.","triggerScenarios":"Running a `GAP FILL` query whose time index column is not TIMESTAMP or TIMESTAMPTZ (e.g. a DATE, TIME, or integer column) so the `match` on `ScalarRefImpl` falls to the `_ => unreachable!(...)` arm at src/stream/src/executor/gap_fill.rs:394.","commonSituations":"Users gap-filling over a DATE-typed column or a numeric epoch column; schema changes that altered the time column type after the MV was created.","solutions":["Cast the time column to TIMESTAMP/TIMESTAMPTZ before gap-filling, e.g. `GAP FILL ... ORDER BY time_col::TIMESTAMP`.","If using an epoch integer column, convert it with `TO_TIMESTAMP(col)` in the ORDER BY expression.","If the column already appears to be timestamp-typed, check for a DATE/TIMESTAMP mismatch and report a frontend validation gap that allowed the unsupported type."],"exampleFix":"// before\nSELECT GAP FILL(time_col, INTERVAL '1 minute') FROM t GROUP BY time_col;\n// after\nSELECT GAP FILL(time_col::TIMESTAMP, INTERVAL '1 minute') FROM t GROUP BY time_col::TIMESTAMP;","handlingStrategy":"validation","validationCode":"-- Before creating a gap-fill MV, verify the time column type:\nSELECT data_type FROM rw_catalog.rw_columns\nWHERE relation_name = 't' AND name = 'time_col';\n-- must be: timestamp without time zone or timestamp with time zone","typeGuard":"fn is_supported_time_scalar(d: Option<ScalarRefImpl<'_>>) -> bool {\n    matches!(d, Some(ScalarRefImpl::Timestamp(_)) | Some(ScalarRefImpl::Timestamptz(_)))\n}","tryCatchPattern":"// Cast defensively in SQL before the executor sees it:\n// ORDER BY time_col::TIMESTAMPTZ  (or ::TIMESTAMP for naive timestamps)","preventionTips":["Only use TIMESTAMP or TIMESTAMPTZ columns as the gap-fill ORDER BY time column.","Convert DATE or epoch-integer columns explicitly with casts or TO_TIMESTAMP.","Re-check the column type after any upstream schema change."],"tags":["stream-executor","gap-fill","panic","unsupported-type"],"backgroundTag":"unsupported-operation","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"}