risingwavelabs/risingwave · error · Error

failed to match operator

Error message

failed to match operator {from} to {to}: {message}

What it means

A `state_match::Error::Operator` variant raised when an operator node `from` in the old graph cannot be matched to operator `to` in the new graph during schema-change state table matching. `from`/`to` are `StreamNodeDesc` descriptions, and `message` explains why they mismatch (different node type, changed fields, etc.).

Solutions

  1. Read `{from}` vs `{to}` in the message to identify the diverging operator; restrict the ALTER so that operator stays semantically identical.
  2. Recreate the MV/table with the desired definition if the change is inherently incompatible with in-place schema change.
  3. Upgrade both nodes to matching versions if the mismatch stems from operator representation changes between releases.
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

if let state_match::Error::Operator { from, to, message } = &err {
    eprintln!("operator {} -> {} mismatch: {}", from, to, message);
}

Try / catch

match state_match::match_graph(&old, &new) {
    Err(state_match::Error::Operator { from, to, message }) => {
        tracing::warn!("operator change not supported ({} vs {}): {}; recreate the job", from, to, message);
    }
    Err(e) => return Err(e.into()),
    Ok(tables) => apply(tables),
}

Prevention

When it happens

Trigger: Matching graphs where corresponding operators differ — node type changed, node fields (e.g. projection, predicate, aggregator definitions) changed beyond what matching allows — producing this operator-level error, often nested inside Fragment/Graph errors.

Common situations: ALTER statements that change expressions/transforms feeding materialized operators, or version upgrades that alter operator encodings so old and new nodes no longer compare equal.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/meta/src/stream/stream_graph/state_match.rs:66

    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

/// Error type for failed state table matching.
#[derive(thiserror::Error, thiserror_ext::Macro, thiserror_ext::ReportDebug)]
pub(crate) enum Error {
    #[error("failed to match graph: {message}")]
    Graph { message: String },

    #[error("failed to match fragment {id}: {message}")]
    Fragment {
        source: Option<Box<Error>>,
        id: Id,
        message: String,
    },

    #[error("failed to match operator {from} to {to}: {message}")]
    Operator {
        from: StreamNodeDesc,
        to: StreamNodeDesc,
        message: String,
    },
}

type Result<T, E = Error> = std::result::Result<T, E>;

/// Fragment id.
type Id = FragmentId;

/// Node for a fragment in the [`Graph`].
struct Fragment {
    /// The fragment id.
    id: Id,
    /// The root node of the fragment.
    root: StreamNode,

View on GitHub (pinned to 6469eb736d)