risingwavelabs/risingwave · error
unknown fill strategy
Error message
unknown fill strategy: {} What it means
The EOWC (emit-on-window-close) gap fill conversion validates each fill strategy string from the proto node against the known set: "locf", "interpolate", "null". Any other string fails conversion in `new_boxed_executor` with this error naming the unknown value.
Solutions
- Use one of the supported strategies: locf, interpolate, or null.
- Upgrade the stream compute node so its FillStrategy enum matches the frontend's emitted values.
- Inspect the fragment proto to find which strategy string is being sent and correct the query/planner.
Example fix
-- before
GAP FILL (FILL-strategy 'linear')
-- after
GAP FILL (... FILL ('locf')) -- or 'interpolate' / 'null' Defensive patterns
Strategy: validation
Validate before calling
// before sending the proto const VALID: [&str; 3] = ["locf", "interpolate", "null"]; assert!(strategies.iter().all(|s| VALID.contains(&s.as_str())), "unknown fill strategy");
Type guard
fn is_valid_strategy(s: &str) -> bool {
matches!(s, "locf" | "interpolate" | "null")
} Prevention
- Only use documented fill strategies in queries
- Keep the frontend's strategy list and the stream enum in sync
- Upgrade frontend and stream nodes together
When it happens
Trigger: A `FillNode`/gap-fill proto carries a fill strategy string other than locf/interpolate/null, so the `match s.as_str()` arm hits the `_ => bail!` branch during actor building.
Common situations: Frontend (newer version) emitting a fill strategy the stream node (older version) does not know; a typo or corrupt value in the plan proto; hand-crafted test plans with bogus strategy strings.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unknown fill strategy
- Gap interval expression returned null
- Gap interval must be positive
- Time column should be Timestamp or Timestamptz
- a stream has reached the end but some other stream has not…
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/bec37b96a5978615.
Report an issue: GitHub.
Appendix: source
Thrown at src/stream/src/from_proto/eowc_gap_fill.rs:65
// Parse interval from ExprNode
let interval_expr_node = node.get_interval()?;
let gap_interval =
build_non_strict_from_prost(interval_expr_node, params.eval_error_report.clone())?;
let fill_columns: Vec<usize> = node
.get_fill_columns()
.iter()
.map(|&x| x as usize)
.collect();
let fill_strategies: Vec<FillStrategy> = node
.get_fill_strategies()
.iter()
.map(|s| match s.as_str() {
"locf" => Ok(FillStrategy::Locf),
"interpolate" => Ok(FillStrategy::Interpolate),
"null" => Ok(FillStrategy::Null),
_ => anyhow::bail!("unknown fill strategy: {}", s),
})
.collect::<anyhow::Result<_>>()?;
let fill_columns_with_strategies: HashMap<usize, FillStrategy> =
fill_columns.into_iter().zip_eq(fill_strategies).collect();
let vnodes = params.vnode_bitmap.map(Arc::new);
let prev_row_table =
StateTableBuilder::new(node.get_prev_row_table().as_ref().unwrap(), store, vnodes)
.forbid_preload_all_rows()
.build()
.await;
let partition_by_indices: Vec<usize> = node
.get_partition_by_indices()
.iter()
.map(|&x| x as usize)View on GitHub (pinned to 6469eb736d)