{"record":{"id":"31fa9d129c806a28","repo":"risingwavelabs/risingwave","slug":"iceberg-metadata-type-is-unspecified","errorCode":null,"errorMessage":"Iceberg metadata type is unspecified","messagePattern":"Iceberg metadata type is unspecified","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/batch/executors/src/executor/iceberg_metadata_scan.rs","lineNumber":92,"sourceCode":"        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\n            .time_travel\n            .as_ref()\n            .map(|time_travel| match time_travel {\n                TimeTravel::SnapshotId(snapshot_id) => IcebergTimeTravelInfo::Version(*snapshot_id),\n                TimeTravel::TimestampMs(timestamp_ms) => {\n                    IcebergTimeTravelInfo::TimestampMs(*timestamp_ms)\n                }\n            });\n        let config = ConnectorProperties::extract(\n            WithOptionsSecResolved::new(node.with_properties.clone(), node.secret_refs.clone()),\n            false,\n        )?;\n        let ConnectorProperties::Iceberg(properties) = config else {\n            return Err(anyhow!(\"Iceberg metadata scan received a non-Iceberg connector\").into());\n        };","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/batch/executors/src/executor/iceberg_metadata_scan.rs#L74-L110","documentation":"Size-bound violation on the update path: decoding an update contributes two ops (`Op::UpdateDelete` and `Op::UpdateInsert`), and the running `ops.len()` exceeded `size_bound` after pushing both. This guards against oversized chunks consuming unbounded memory during decode.","triggerScenarios":"Calling `deserialize_stream_chunk` where decoded update pairs push total op count past `size_bound` (checked after `read_update(row_size)` and the two `ops.push` calls). Thrown at serde.rs:499.","commonSituations":"Write side packing many update pairs into one chunk while the reader uses a size_bound counted in single rows (each update counts as two); read ranges covering more than one chunk's worth of updates.","solutions":["Make the write side count updates as two ops against size_bound when serializing chunks.","Tighten the read range selection so it stops before exceeding size_bound ops.","Increase size_bound consistently on both writer and reader if larger chunks are intended.","Check for duplicated update entries in the KV store causing the count to inflate."],"exampleFix":"// before\n// writer counts each update as 1 op toward size_bound\nif chunk_ops.len() > size_bound { flush(); }\n// after\nif chunk_ops.len() + 2 > size_bound { flush(); } // update = delete + insert\n","handlingStrategy":"validation","validationCode":"// rust\n// count an update pair as 2 ops when checking size_bound before write\nanyhow::ensure!(pending_ops + 2 <= size_bound, \"update pair would exceed size_bound {}\", size_bound);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat every update pair as two ops in size accounting on both write and read paths.","Align size_bound configuration between writer and reader.","Cap read ranges so decoded op count stays within bounds."],"tags":["log-store","deserialization","size-bound","update-delete-insert"],"backgroundTag":"value-out-of-range","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"}