risingwavelabs/risingwave · error

unknown MATCH_RECOGNIZE input mode: {}

Error message

unknown MATCH_RECOGNIZE input mode: {}

What it means

MATCH_RECOGNIZE input mode is transported as a protobuf enum. A wire value outside the known enum range decodes as `Unspecified`, which would silently be treated as event-time — the correctness contract of the executor. The decode path therefore rejects a non-zero raw value that reads back as `Unspecified`, guarding against future/unknown enum variants from newer frontends.

Source

Thrown at src/stream/src/from_proto/match_recognize.rs:57

    async fn new_boxed_executor(
        params: ExecutorParams,
        node: &MatchRecognizeNode,
        store: impl StateStore,
    ) -> StreamResult<Executor> {
        let [input]: [_; 1] = params.input.try_into().unwrap();

        // This executor's entire correctness rests on the ordered-input contract the EVENT_TIME
        // plan (an EowcSort upstream in the same fragment) provides. A different input mode —
        // PROCESSING_TIME is reserved, unimplemented — must fail here, not silently run against
        // rows whose ordering guarantee does not hold.
        // An out-of-range wire value decodes as `Unspecified` through the accessor, which would
        // silently run an unknown future mode as event-time — the one contract this executor's
        // correctness rests on. Reject it like every other enum in this decode path; a raw 0
        // (genuinely unset) is accepted as event-time since this frontend always writes it.
        if node.input_mode != 0 && node.input_mode() == MatchRecognizeInputMode::Unspecified {
            return Err(
                anyhow::anyhow!("unknown MATCH_RECOGNIZE input mode: {}", node.input_mode).into(),
            );
        }
        match node.input_mode() {
            MatchRecognizeInputMode::Unspecified | MatchRecognizeInputMode::EventTime => {}
            other => {
                return Err(
                    anyhow::anyhow!("unsupported MATCH_RECOGNIZE input mode: {other:?}").into(),
                );
            }
        }

        let partition_key_indices = node.partition_by.iter().map(|&i| i as usize).collect();
        // ORDER BY is carried as `ColumnOrder`. v1 only supports the default ascending order (the
        // binder rejects anything else); assert it here too so a non-ascending plan fails fast
        // rather than being silently sorted ascending by the executor.
        let order_key_indices = node
            .order_by
            .iter()

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Upgrade the compute node (and all binaries) to the same version as the frontend that emitted the new input mode.
  2. Re-generate the streaming job so the plan uses a mode the running binaries understand.
  3. Inspect the actor proto's `input_mode` field for an out-of-range value.
  4. If intentional, extend the executor's match arm to support the new mode before deploying it.

Example fix

// before
if node.input_mode != 0 && node.input_mode() == MatchRecognizeInputMode::Unspecified { /* reject */ }
// after: keep the guard, but upgrade binaries so the new mode maps to a known variant
MatchRecognizeInputMode::StreamingTime => { /* handle new mode explicitly */ }
Defensive patterns

Strategy: validation

Validate before calling

// decode guard before executor construction
if node.input_mode != 0 && node.input_mode() == MatchRecognizeInputMode::Unspecified {
    return Err(anyhow!("unknown MATCH_RECOGNIZE input mode: {}", node.input_mode));
}

Type guard

fn is_known_input_mode(v: i32) -> bool {
    MatchRecognizeInputMode::try_from(v).is_ok()
}

Try / catch

match MatchRecognizeInputMode::try_from(node.input_mode) { Ok(m) => use(m), Err(_) => Err(anyhow!("unknown MATCH_RECOGNIZE input mode: {}", node.input_mode)) }

Prevention

When it happens

Trigger: `new_boxed_executor` for the MATCH_RECOGNIZE node sees `node.input_mode != 0` while the protobuf accessor maps it to `MatchRecognizeInputMode::Unspecified` — i.e. an unrecognized/out-of-range integer on the wire (e.g. a mode added by a newer frontend).

Common situations: Version skew: compute node older than the frontend that introduced a new input mode; corrupted or hand-edited plan protos; replaying plan fragments across versions.

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


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/b6ee09614268372c. Report an issue: GitHub.