risingwavelabs/risingwave · error

expected but got

Error message

expected {} but got {:?}

What it means

A macro-generated TryFrom<SplitImpl> conversion failed: the SplitImpl enum held a different connector's split variant than the one being downcast to. risingwave_common::bail! produces 'expected <Variant> but got <actual>'. Note the eq/partial_cmp uses shown at top_n.rs are unrelated PartialEq impls; the error itself originates in the macro's try_from.

Solutions

  1. Check the WITH connector type of the source/table matches the expected split type
  2. Recreate the sink/source or restart the query so splits are regenerated for the correct connector
  3. If seen after a version upgrade, clear stale split state (recovery/recreate) and report the mismatch

Example fix

// before
let s: KafkaSplit = split.try_into()?; // split is actually an IcebergSplit
// after
let SplitImpl::Kafka(s) = &split else { return Err(anyhow!("unexpected split {:?}", split)); };
Defensive patterns

Strategy: type-guard

Validate before calling

fn expect_kafka_split(split: &SplitImpl) -> Option<&KafkaSplit> {
    match split { SplitImpl::Kafka(s) => Some(s), _ => None }
}

Type guard

fn as_variant<T: 'static>(split: &SplitImpl, f: impl Fn(&SplitImpl) -> Option<&T>) -> Option<&T> { f(split) }
// or simply:
fn is_kafka(split: &SplitImpl) -> bool { matches!(split, SplitImpl::Kafka(_)) }

Try / catch

let kafka_split: KafkaSplit = SplitImpl::try_from(split.clone())
    .map_err(|e| anyhow!("split routing mismatch: {}", e))?;

Prevention

When it happens

Trigger: Casting a SplitImpl to a concrete split type (e.g. SplitImpl::try_into::<KafkaSplit>()) when the split actually belongs to another connector, typically due to mixed-up sources, a scheduler bug, or misconfigured fragment/split assignment.

Common situations: Batch execution or recovery after a catalog change where splits persisted for one connector are replayed against another; running queries over a source whose connector type changed; internal split-routing bugs.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at src/connector/src/macros.rs:307

#[macro_export]
macro_rules! impl_split {
    ({$({ $variant_name:ident, $prop_name:ty, $split:ty}),*}) => {

        #[derive(Debug, Clone, EnumAsInner, PartialEq)]
        pub enum SplitImpl {
            $(
                $variant_name($split),
            )*
        }

        $(
            impl TryFrom<SplitImpl> for $split {
                type Error = $crate::error::ConnectorError;

                fn try_from(split: SplitImpl) -> std::result::Result<Self, Self::Error> {
                    match split {
                        SplitImpl::$variant_name(inner) => Ok(inner),
                        other => risingwave_common::bail!(
                            "expected {} but got {:?}",
                            stringify!($split),
                            other
                        ),
                    }
                }
            }

            impl From<$split> for SplitImpl {
                fn from(split: $split) -> SplitImpl {
                    SplitImpl::$variant_name(split)
                }
            }

        )*
    }
}

View on GitHub (pinned to 6469eb736d)