risingwavelabs/risingwave · error · StreamExecutorError

iceberg pk-index writer {} received mismatched left/right ba

Error message

iceberg pk-index writer {} received mismatched left/right barriers: left={:?}, right={:?}

What it means

The pk-index writer is a two-input executor whose left (data/sink) and right (resolver) streams must see identical barriers: same epoch, same kind, and same mutation. validate_aligned_barriers enforces this; a mismatch means the two streams have diverged and continuing could corrupt the pk index or the Iceberg commit.

Source

Thrown at src/stream/src/executor/iceberg_with_pk_index/writer.rs:348

                Ok(())
            }
            _ => bail!(
                "iceberg pk-index writer {} expected matching {:?} context for task {}, got {:?}",
                self.sink_id,
                expected_phase,
                expected_task,
                barrier
            ),
        }
    }

    fn validate_aligned_barriers(
        &self,
        left: &Barrier,
        right: &Barrier,
    ) -> StreamExecutorResult<()> {
        if left.epoch != right.epoch || left.kind != right.kind || left.mutation != right.mutation {
            bail!(
                "iceberg pk-index writer {} received mismatched left/right barriers: left={:?}, right={:?}",
                self.sink_id,
                left,
                right
            );
        }
        Ok(())
    }

    fn compaction_begin(
        &self,
        barrier: &Barrier,
    ) -> StreamExecutorResult<Option<IcebergCompactionTaskId>> {
        let context = match barrier.iceberg_pk_index_compaction() {
            Some(context) if context.sink_id == self.sink_id => context,
            _ => return Ok(None),
        };
        if context.phase == Phase::End as i32 {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Log both barriers and identify which field diverged (epoch, kind, or mutation).
  2. Restart the fragment from the last checkpoint so both inputs realign.
  3. Check the fragment's actor graph for asymmetric mutation application (one side only).
  4. Verify barrier dispatch from meta reaches both inputs symmetrically.
  5. File a bug with both barrier Debug dumps if reproducible.
Defensive patterns

Strategy: validation

Validate before calling

// assert symmetry before forwarding barriers to the two-input writer
assert_eq!(left.epoch, right.epoch);
assert_eq!(left.kind, right.kind);
assert_eq!(left.mutation, right.mutation);

Type guard

fn barriers_aligned(left: &Barrier, right: &Barrier) -> bool {
    left.epoch == right.epoch && left.kind == right.kind && left.mutation == right.mutation
}

Try / catch

if let Err(e) = writer.execute_inner(...).await {
    if e.to_string().contains("mismatched left/right barriers") {
        error!("input streams diverged; recovering both inputs from last checkpoint");
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Raised in validate_aligned_barriers (called from execute_inner, execute_normal, execute_aligning_replacement_input) when left.epoch != right.epoch, left.kind != right.kind, or left.mutation != right.mutation for the pair of barriers drawn from the two inputs.

Common situations: Uneven upstream backpressure or failure causing one input to advance epochs ahead of the other; a mutation (e.g. pause/resume, config change) applied to only one branch; topology rewiring after scale-in/out breaking barrier symmetric delivery.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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