{"record":{"id":"c96640a6e10a527c","repo":"risingwavelabs/risingwave","slug":"iceberg-metadata-scan-should-not-have-input-execut","errorCode":null,"errorMessage":"Iceberg metadata scan should not have input executors","messagePattern":"Iceberg metadata scan should not have input executors","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/batch/executors/src/executor/iceberg_metadata_scan.rs","lineNumber":77,"sourceCode":"            table,\n            self.metadata_type,\n            self.time_travel_info,\n            self.chunk_size,\n        ) {\n            yield chunk?;\n        }\n    }\n}\n\npub struct IcebergMetadataScanExecutorBuilder;\n\nimpl BoxedExecutorBuilder for IcebergMetadataScanExecutorBuilder {\n    async fn new_boxed_executor(\n        source: &ExecutorBuilder<'_>,\n        inputs: Vec<BoxedExecutor>,\n    ) -> crate::error::Result<BoxedExecutor> {\n        ensure!(\n            inputs.is_empty(),\n            \"Iceberg metadata scan should not have input executors\"\n        );\n        let node = try_match_expand!(\n            source.plan_node().get_node_body().unwrap(),\n            NodeBody::IcebergMetadataScan\n        )?;\n\n        let metadata_type = match MetadataType::try_from(node.metadata_type)\n            .context(\"invalid Iceberg metadata type\")?\n        {\n            MetadataType::Snapshots => IcebergMetadataTableType::Snapshots,\n            MetadataType::Manifests => IcebergMetadataTableType::Manifests,\n            MetadataType::Files => IcebergMetadataTableType::Files,\n            MetadataType::Unspecified => {\n                return Err(anyhow!(\"Iceberg metadata type is unspecified\").into());\n            }\n        };\n        let time_travel_info = node","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/batch/executors/src/executor/iceberg_metadata_scan.rs#L59-L95","documentation":"Same epoch-consistency check as error 2022 but for the update path: when decoding a `LogStoreOp::Update` (UpdateDelete/UpdateInsert pair), the row's `row_meta.epoch` must equal the read's `expected_epoch`. A mismatch means the stored update was tagged with a different epoch than the range being read, and the decoder refuses to emit the pair.","triggerScenarios":"Calling `deserialize_stream_chunk` on a range where a stored `LogStoreOp::Update` row has `row_meta.epoch != expected_epoch`. Thrown at serde.rs:489.","commonSituations":"Writer tagging update rows with a stale epoch across a barrier; reads whose expected epoch was computed from a different barrier; store corruption from an unclean shutdown mid-write.","solutions":["Check the serialize path writes `row_meta.epoch` from the same barrier epoch used to compute expected_epoch on read.","Confirm update rows are never split across epoch boundaries when buffered/flushed.","Inspect the offending seq id's row_meta to detect corruption or miswritten epochs.","Ensure the read range was selected for the epoch that actually contains the rows."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// rust\n// ensure updates are flushed within a single epoch\nanyhow::ensure!(update_epoch == barrier_epoch, \"update tagged epoch {} but flush epoch {}\", update_epoch, barrier_epoch);","typeGuard":null,"tryCatchPattern":"// rust\nmatch reader.deserialize_stream_chunk(start, end, expected_epoch).await {\n    Ok(chunk) => process(chunk),\n    Err(e) if e.to_string().contains(\"decoded epoch\") => {\n        tracing::error!(\"update epoch mismatch, possible corruption: {e:#}\");\n        // route to recovery instead of retrying the same read\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Serialize update rows with the epoch of the barrier they belong to.","Never split update pairs across epoch flush boundaries.","Verify store contents after unclean shutdowns (checksums/scan)."],"tags":["log-store","deserialization","epoch","update-delete-insert"],"backgroundTag":"checksum-mismatch","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}