risingwavelabs/risingwave · error

meta client is required for iceberg pk-index position-delete

Error message

meta client is required for iceberg pk-index position-delete merger

What it means

The iceberg pk-index position-delete merger executor needs a meta client to coordinate position delete file merging across parallelities. `new_boxed_executor` fails fast with this anyhow error when `params.env.meta_client()` is `None`. Like the compaction resolver, the merger cannot operate without meta-side coordination, so the error is raised at executor build time.

Source

Thrown at src/stream/src/from_proto/iceberg_with_pk_index/position_delete_merger.rs:53

    async fn new_boxed_executor(
        params: ExecutorParams,
        node: &Self::Node,
        _store: impl StateStore,
    ) -> StreamResult<Executor> {
        let [input]: [_; 1] = params.input.try_into().unwrap();

        let sink_desc = node.sink_desc.as_ref().unwrap();
        let sink_id: SinkId = sink_desc.get_id();

        let properties_with_secret = LocalSecretManager::global().fill_secrets(
            sink_desc.get_properties().clone(),
            sink_desc.get_secret_refs().clone(),
        )?;
        let config = IcebergConfig::from_btreemap(properties_with_secret)
            .map_err(|err| StreamExecutorError::sink_error(err, sink_id))?;
        let meta_client = params.env.meta_client().ok_or_else(|| {
            anyhow!("meta client is required for iceberg pk-index position-delete merger")
        })?;

        let handler = PositionDeleteHandlerImpl::new(
            config,
            params.actor_context.id,
            params.vnode_bitmap.clone(),
            sink_id,
            meta_client,
        );

        let exec = PositionDeleteMergerExecutor::new(
            params.actor_context.id,
            sink_id,
            params.local_barrier_manager.clone(),
            input,
            handler,
        );
        Ok((params.info, exec).into())

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Start the node in a real cluster so a meta client is available in the stream environment.
  2. In tests, construct the environment with a mock meta client implementation.
  3. Check compute node configuration/startup to ensure the meta client is initialized before executor building.
  4. Remove or reconfigure the Iceberg pk-index sink if meta coordination is unavailable.

Example fix

// before
let env = StreamEnvironment::for_test(); // meta_client() == None
// after
let env = StreamEnvironment::new(config, Some(meta_client));
Defensive patterns

Strategy: validation

Validate before calling

// before constructing the merger
if params.env.meta_client().is_none() {
    panic!("position-delete merger requires meta client; use a cluster-backed environment");
}

Type guard

fn meta_client_or_none(env: &StreamEnvironment) -> Option<MetaClientRef> { env.meta_client() }

Try / catch

let meta_client = env.meta_client().ok_or_else(|| anyhow!("meta client is required"))?;

Prevention

When it happens

Trigger: Constructing a `PositionDeleteMerger` executor from its proto node when the stream environment lacks a meta client (`params.env.meta_client()` returns `None`), right after building `IcebergConfig` from the sink properties.

Common situations: Embedded or test environments without a meta client; simulation runs (madsim) where meta client wiring differs; a compute node started without meta connection attempting to serve an Iceberg pk sink graph.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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