{"record":{"id":"378603c5154a70a8","repo":"risingwavelabs/risingwave","slug":"can-t-create-iceberg-sink-write-result-from-empty","errorCode":null,"errorMessage":"Can't create iceberg sink write result from empty data!","messagePattern":"Can't create iceberg sink write result from empty data!","errorType":"exception","errorClass":"SinkError::Iceberg","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/commit.rs","lineNumber":64,"sourceCode":"use crate::connector_common::{IcebergCommittedSnapshot, IcebergSinkCompactionUpdate};\nuse crate::sink::catalog::SinkId;\nuse crate::sink::{Result, SinglePhaseCommitCoordinator, SinkParam, TwoPhaseCommitCoordinator};\n\nconst SCHEMA_ID: &str = \"schema_id\";\nconst PARTITION_SPEC_ID: &str = \"partition_spec_id\";\nconst DATA_FILES: &str = \"data_files\";\n\n#[derive(Default, Clone)]\npub struct IcebergCommitResult {\n    pub schema_id: i32,\n    pub partition_spec_id: i32,\n    pub data_files: Vec<SerializedDataFile>,\n}\n\nimpl IcebergCommitResult {\n    pub fn try_from(value: &SinkMetadata) -> Result<Self> {\n        let Some(Serialized(value)) = &value.metadata else {\n            bail!(\"Can't create iceberg sink write result from empty data!\");\n        };\n\n        Self::try_from_serialized_bytes(&value.metadata)\n    }\n\n    pub fn try_from_serialized_bytes(value: &[u8]) -> Result<Self> {\n        let mut values = if let serde_json::Value::Object(value) =\n            serde_json::from_slice::<serde_json::Value>(value)\n                .context(\"Can't parse iceberg sink metadata\")?\n        {\n            value\n        } else {\n            bail!(\"iceberg sink metadata should be an object\");\n        };\n\n        let schema_id;\n        if let Some(serde_json::Value::Number(value)) = values.remove(SCHEMA_ID) {\n            schema_id = value","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/commit.rs#L46-L82","documentation":"When committing an Iceberg sink, `IcebergCommitResult::try_from` deserializes the stored SinkMetadata. If `value.metadata` is absent (not `Serialized(_)`), there are no serialized data files to build a commit result from, so it bails with this error.","triggerScenarios":"Reading sink metadata (e.g. during MV/commit recovery or `SinkCommittedResult` handling) where the SinkMetadata was never written — e.g. the sink epoch produced no metadata, or the metadata field is empty/None in the persisted record.","commonSituations":"Corrupted or pruned metadata in the meta store; recovering a sink whose previous epoch never emitted metadata; version/serialization changes causing metadata to be dropped; bug in the metadata-writing path.","solutions":["Check whether the sink ever committed metadata; if the epoch legitimately wrote no files, ensure the empty-metadata case is handled upstream before calling try_from","Inspect the meta store / sink metadata records for the affected epoch","Drop and recreate the sink if its metadata is unrecoverable","Verify connector/node versions are consistent to avoid serialization mismatches"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// guard before calling IcebergCommitResult::try_from\nif !matches!(meta.metadata, Some(Serialized(_))) {\n    // handle empty-metadata epoch explicitly\n    return Ok(IcebergCommitResult::default());\n}","typeGuard":"fn has_serialized_metadata(m: &SinkMetadata) -> bool {\n    matches!(m.metadata, Some(Serialized(_)))\n}","tryCatchPattern":"let res = IcebergCommitResult::try_from(&meta);\nif let Err(e) = &res {\n    if e.to_string().contains(\"from empty data\") {\n        // treat as no-op commit or alert on missing metadata\n    }\n}","preventionTips":["Verify the sink actually wrote metadata for the epoch before committing","Monitor meta store records for missing sink metadata","Keep RisingWave versions consistent to avoid metadata format drift"],"tags":["sink","iceberg","metadata","internal"],"backgroundTag":"empty-required-field","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"}