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
- Exclude barrier entries from the read range (stop end_seq_id before the barrier's seq id).
- Route barrier ops to the barrier-decoding path (`next_op` / barrier alignment) instead of `deserialize_stream_chunk`.
- Check seq-id bookkeeping so data reads never overlap barrier writes.
- 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
- Exclude barrier seq ids from data-read ranges.
- Handle barriers on the dedicated barrier decode path.
- Re-read the barrier position if writes may land between range selection and read.
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
- Exchange executor should not have children!
- GetChannelDeltaStatsExecutor should have no child!
- Iceberg metadata scan should not have input executors
- Iceberg metadata type is unspecified
- file_scan_tasks must be Some
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/c15726d221a77dff.
Report an issue: GitHub.