risingwavelabs/risingwave · error

Iceberg metadata scan received a non-Iceberg connector

Error message

Iceberg metadata scan received a non-Iceberg connector

What it means

`deserialize_stream_chunk` is only meant to decode data rows; a stored `LogStoreOp::Barrier` inside the requested `[start_seq_id, end_seq_id)` seq-id range is not decodable into a stream chunk, so the decoder fails fast. Barriers must be handled by the barrier-specific decode path instead.

Source

Thrown at src/batch/executors/src/executor/iceberg_metadata_scan.rs:109

            MetadataType::Unspecified => {
                return Err(anyhow!("Iceberg metadata type is unspecified").into());
            }
        };
        let time_travel_info = node
            .time_travel
            .as_ref()
            .map(|time_travel| match time_travel {
                TimeTravel::SnapshotId(snapshot_id) => IcebergTimeTravelInfo::Version(*snapshot_id),
                TimeTravel::TimestampMs(timestamp_ms) => {
                    IcebergTimeTravelInfo::TimestampMs(*timestamp_ms)
                }
            });
        let config = ConnectorProperties::extract(
            WithOptionsSecResolved::new(node.with_properties.clone(), node.secret_refs.clone()),
            false,
        )?;
        let ConnectorProperties::Iceberg(properties) = config else {
            return Err(anyhow!("Iceberg metadata scan received a non-Iceberg connector").into());
        };

        Ok(Box::new(IcebergMetadataScanExecutor {
            schema: metadata_type.schema(),
            properties: *properties,
            metadata_type,
            time_travel_info,
            identity: source.plan_node().get_identity().clone(),
            chunk_size: source.context().get_config().developer.chunk_size,
        }))
    }
}

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Exclude barrier entries from the read range (stop end_seq_id before the barrier's seq id).
  2. Route barrier ops to the barrier-decoding path (`next_op` / barrier alignment) instead of `deserialize_stream_chunk`.
  3. Check seq-id bookkeeping so data reads never overlap barrier writes.
  4. If this happens during recovery, ensure replay alternates correctly between data ranges and barriers.
Defensive patterns

Strategy: validation

Validate before calling

// rust
// stop the data range before the first barrier seq id
let end = end_seq_id.min(next_barrier_seq_id - 1);
anyhow::ensure!(end > start_seq_id, "no data rows between {} and barrier at {}", start_seq_id, next_barrier_seq_id);

Try / catch

// rust
match reader.deserialize_stream_chunk(start, end, epoch).await {
    Ok(chunk) => process(chunk),
    Err(e) if e.to_string().contains("should not get barrier") => {
        // recompute the range excluding barrier seq ids and retry once
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `deserialize_stream_chunk` on a seq-id range that includes a written `LogStoreOp::Barrier` entry (matched by the `(_, LogStoreOp::Barrier { .. })` arm). Thrown at serde.rs:509.

Common situations: Reader range-selection logic including barrier seq ids when fetching data rows; races where a barrier is written between computing start_seq_id and end_seq_id; callers using the chunk decoder on a mixed range during recovery replay.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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