risingwavelabs/risingwave · error

Iceberg metadata relations are not supported in streaming qu

Error message

Iceberg metadata relations are not supported in streaming queries

What it means

LogicalIcebergMetadataScan represents Iceberg metadata relations (e.g. metadata tables/files). The streaming optimizer calls to_stream when converting logical plans to streaming plans; this node deliberately rejects streaming with a bail! because Iceberg metadata relations are designed to be read only via batch queries. The error is an intended guard, not a crash.

Source

Thrown at src/frontend/src/optimizer/plan_node/logical_iceberg_metadata_scan.rs:91

        predicate: Condition,
        _ctx: &mut PredicatePushdownContext,
    ) -> PlanRef {
        LogicalFilter::create(self.clone().into(), predicate)
    }
}

impl ToBatch for LogicalIcebergMetadataScan {
    fn to_batch(&self) -> Result<crate::optimizer::plan_node::BatchPlanRef> {
        Ok(BatchIcebergMetadataScan::new(self.core.clone()).into())
    }
}

impl ToStream for LogicalIcebergMetadataScan {
    fn to_stream(
        &self,
        _ctx: &mut ToStreamContext,
    ) -> Result<crate::optimizer::plan_node::StreamPlanRef> {
        bail!("Iceberg metadata relations are not supported in streaming queries")
    }

    fn logical_rewrite_for_stream(
        &self,
        _ctx: &mut RewriteStreamContext,
    ) -> Result<(PlanRef, ColIndexMapping)> {
        bail!("Iceberg metadata relations are not supported in streaming queries")
    }
}

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Run the query as a batch query (plain SELECT) instead of a streaming/materialized query — Iceberg metadata relations are batch-only.
  2. Materialize the needed metadata snapshot in a batch job/table and build streaming logic on that materialized data instead.
  3. Check RisingWave docs/release notes for Iceberg metadata relation streaming support; upgrade if a newer version adds it.

Example fix

// before: streaming query over Iceberg metadata
CREATE MATERIALIZED VIEW mv FROM iceberg_meta_scan(...);
// after: batch query
SELECT * FROM iceberg_meta_scan(...);
Defensive patterns

Strategy: validation

Validate before calling

// Detect Iceberg metadata relations before issuing streaming DDL
let is_iceberg_metadata = sql.to_uppercase().contains(".$METADATA") || relation_name.contains("iceberg_meta");
if is_iceberg_metadata {
    return Err("Iceberg metadata relations are batch-only".into());
}

Type guard

fn is_batch_only_relation(kind: &RelationKind) -> bool {
    matches!(kind, RelationKind::IcebergMetadataScan)
}

Try / catch

match client.run_sql(stmt) {
    Err(e) if format!("{e}").contains("not supported in streaming") => {
        eprintln!("Run this as a batch query instead: {}", to_batch_sql(stmt));
    }
    r => r?,
}

Prevention

When it happens

Trigger: Running a streaming query (CREATE MATERIALIZED VIEW, CREATE STREAM, shared source plan) whose plan references an Iceberg metadata relation (e.g. querying an Iceberg metadata table inside a streaming context), causing to_stream to be invoked on LogicalIcebergMetadataScan.

Common situations: Developers building materialized views on top of Iceberg metadata tables (like iceberg.$files / metadata scans), assuming continuous querying is supported; using SQL that mixes Iceberg metadata relations into streaming pipelines after a version where the guard was added.

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/396dffa7f1863d7e. Report an issue: GitHub.