risingwavelabs/risingwave · error

iceberg pk-index sink report has invalid role: {}

Error message

iceberg pk-index sink report has invalid role: {}

What it means

During commit coordination, the meta service aggregates status reports from all workers participating in an Iceberg pk-index sink. Each report carries a protobuf enum `role` that must be Writer or PositionDeleteMerger; if the raw i32 does not map to a valid variant, or maps to `Unspecified`, the wire format is corrupt and `aggregate_reports` aborts the commit with this anyhow error.

Source

Thrown at src/meta/src/manager/iceberg_pk_index_sink/coordinator.rs:580

    let mut data_files: Vec<SerializedDataFile> = Vec::new();
    let mut delete_files: Vec<SerializedDataFile> = Vec::new();
    let mut overwrite_files: Vec<SerializedDataFile> = Vec::new();

    if reports.is_empty() {
        bail!("no reports to aggregate for iceberg pk-index sink coordinator");
    }

    for r in reports {
        let Some(meta) = &r.metadata else {
            bail!("iceberg pk-index sink report missing metadata in aggregate_reports");
        };

        // Validate role: explicitly-Unspecified is a wire-format bug.
        let role = PbIcebergPkIndexSinkRole::try_from(r.role)
            .ok()
            .filter(|r| !matches!(r, PbIcebergPkIndexSinkRole::Unspecified))
            .ok_or_else(|| anyhow!("iceberg pk-index sink report has invalid role: {}", r.role))?;

        match role {
            PbIcebergPkIndexSinkRole::Writer => {
                let commit_result = IcebergCommitResult::try_from(meta)?;
                align_report_id(
                    commit_result.schema_id,
                    commit_result.partition_spec_id,
                    &mut shared_schema_id,
                    &mut shared_partition_spec_id,
                )?;
                data_files.extend(commit_result.data_files);
            }
            PbIcebergPkIndexSinkRole::PositionDeleteMerger => {
                let commit_result =
                    IcebergPositionDeleteCommitResult::try_from(meta).map_err(|e| {
                        anyhow!(e).context("decode pk-index sink position-delete merger metadata")
                    })?;
                align_report_id(

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Upgrade all worker nodes to the same version as the meta node so the role field is always populated.
  2. Fix the worker code that builds the sink report to explicitly set role to Writer or PositionDeleteMerger.
  3. Log/inspect the report's raw role value to identify the offending node and invalid value.
  4. Restart the offending worker and retry the sink commit.

Example fix

// before (worker builds report with default role)
let report = PbIcebergPkIndexSinkReport { report_meta: Some(meta), ..Default::default() };
// after
let report = PbIcebergPkIndexSinkReport {
    role: PbIcebergPkIndexSinkRole::Writer as i32,
    report_meta: Some(meta),
    ..Default::default()
};
Defensive patterns

Strategy: validation

Validate before calling

// worker-side, before sending the report
let role = PbIcebergPkIndexSinkRole::try_from(report.role)
    .ok()
    .filter(|r| *r != PbIcebergPkIndexSinkRole::Unspecified)
    .ok_or_else(|| anyhow!("report.role not set: {}", report.role))?;

Type guard

fn is_valid_role(v: i32) -> bool {
    matches!(
        PbIcebergPkIndexSinkRole::try_from(v),
        Ok(PbIcebergPkIndexSinkRole::Writer) | Ok(PbIcebergPkIndexSinkRole::PositionDeleteMerger)
    )
}

Prevention

When it happens

Trigger: IcebergPkIndexSinkCoordinator::pre_commit_epoch -> aggregate_reports iterates worker reports and calls PbIcebergPkIndexSinkRole::try_from(r.role); it fails when a report's role field is 0 (Unspecified, the protobuf default) or any out-of-range i32 value.

Common situations: Version skew between meta and worker binaries so the role field is never set; hand-crafted or replayed report protobufs; a worker bug that forgets to assign the role before sending its commit report.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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