{"record":{"id":"d0e2a20478a6ada4","repo":"risingwavelabs/risingwave","slug":"unknown-fill-strategy-d0e2a2","errorCode":null,"errorMessage":"unknown fill strategy: {}","messagePattern":"unknown fill strategy: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/from_proto/gap_fill.rs","lineNumber":63,"sourceCode":"        // Parse interval from ExprNode\n        let interval_expr_node = node.get_interval()?;\n        let interval_expr =\n            build_non_strict_from_prost(interval_expr_node, params.eval_error_report)?;\n\n        let fill_columns: Vec<usize> = node\n            .get_fill_columns()\n            .iter()\n            .map(|&x| x as usize)\n            .collect();\n\n        let fill_strategies: Vec<FillStrategy> = node\n            .get_fill_strategies()\n            .iter()\n            .map(|s| match s.as_str() {\n                \"locf\" => Ok(FillStrategy::Locf),\n                \"interpolate\" => Ok(FillStrategy::Interpolate),\n                \"null\" => Ok(FillStrategy::Null),\n                _ => anyhow::bail!(\"unknown fill strategy: {}\", s),\n            })\n            .collect::<anyhow::Result<_>>()?;\n\n        let fill_columns_with_strategies: HashMap<usize, FillStrategy> =\n            fill_columns.into_iter().zip_eq(fill_strategies).collect();\n\n        let partition_by_indices: Vec<usize> = node\n            .get_partition_by_indices()\n            .iter()\n            .map(|&x| x as usize)\n            .collect();\n\n        // Hash-distributed state table needs vnodes; singleton (no partition) does not.\n        let vnodes = if partition_by_indices.is_empty() {\n            None\n        } else {\n            Some(std::sync::Arc::new(\n                params","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/from_proto/gap_fill.rs#L45-L81","documentation":"Same family as the EOWC variant: the gap fill conversion maps each strategy string from the proto node to a `FillStrategy`, accepting only \"locf\", \"interpolate\", and \"null\"; anything else aborts `new_boxed_executor` with this message naming the string.","triggerScenarios":"A gap-fill proto node contains a fill strategy string outside the accepted set, so the `match s.as_str()` default arm bails while building the actor.","commonSituations":"Version skew between frontend emitting newer strategies and an older stream node; malformed or hand-edited plan protos; typos in strategy names in generated plans.","solutions":["Use a supported fill strategy: locf, interpolate, or null.","Align frontend and stream node versions so both support the same strategies.","Inspect the plan proto for the offending strategy string and fix the source query/planner."],"exampleFix":"-- before\nFILL ('carry-forward')\n-- after\nFILL ('locf') -- or 'interpolate' / 'null'","handlingStrategy":"validation","validationCode":"// before sending the proto\nconst VALID: [&str; 3] = [\"locf\", \"interpolate\", \"null\"];\nassert!(strategies.iter().all(|s| VALID.contains(&s.as_str())), \"unknown fill strategy\");","typeGuard":"fn is_valid_strategy(s: &str) -> bool {\n    matches!(s, \"locf\" | \"interpolate\" | \"null\")\n}","tryCatchPattern":null,"preventionTips":["Use only locf/interpolate/null in FILL clauses","Version-align frontend and stream components","Validate plan protos in CI before deploying"],"tags":["streaming","gap-fill","config-validation"],"backgroundTag":"invalid-enum-value","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"}