{"record":{"id":"e77259c166031899","repo":"risingwavelabs/risingwave","slug":"can-t-create-iceberg-dv-merger-commit-result-from","errorCode":null,"errorMessage":"Can't create iceberg dv merger commit result from empty data!","messagePattern":"Can't create iceberg dv merger commit result from empty data!","errorType":"exception","errorClass":"SinkError::Iceberg","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/commit.rs","lineNumber":175,"sourceCode":"        );\n        Ok(serde_json::to_vec(&json_value).context(\"Can't serialize iceberg sink metadata\")?)\n    }\n}\n\n#[derive(Default, Clone, Serialize, Deserialize)]\npub struct IcebergPositionDeleteCommitResult {\n    pub schema_id: i32,\n    pub partition_spec_id: i32,\n    pub delete_files: Vec<SerializedDataFile>,\n    pub overwrite_files: Vec<SerializedDataFile>,\n}\n\nimpl<'a> TryFrom<&'a SinkMetadata> for IcebergPositionDeleteCommitResult {\n    type Error = SinkError;\n\n    fn try_from(value: &'a SinkMetadata) -> Result<Self> {\n        let Some(Serialized(value)) = &value.metadata else {\n            bail!(\"Can't create iceberg dv merger commit result from empty data!\");\n        };\n        let value = serde_json::from_slice(&value.metadata)\n            .context(\"Can't deserialize iceberg dv merger commit result from metadata\")?;\n        Ok(value)\n    }\n}\n\nimpl<'a> TryFrom<&'a IcebergPositionDeleteCommitResult> for SinkMetadata {\n    type Error = SinkError;\n\n    fn try_from(value: &'a IcebergPositionDeleteCommitResult) -> Result<SinkMetadata> {\n        let bytes = serde_json::to_vec(value)\n            .context(\"Can't serialize iceberg dv merger commit result to metadata\")?;\n        Ok(SinkMetadata {\n            metadata: Some(Serialized(SerializedMetadata { metadata: bytes })),\n        })\n    }\n}","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/commit.rs#L157-L193","documentation":"IcebergPositionDeleteCommitResult::try_from(&SinkMetadata) requires metadata to be Some(Serialized(..)); if the SinkMetadata carries no serialized payload, the conversion bails. This indicates the position-delete (DV merger) write result was never attached, so there is nothing to deserialize.","triggerScenarios":"Calling TryFrom<&SinkMetadata> for IcebergPositionDeleteCommitResult on a SinkMetadata whose metadata field is None — e.g. an empty write result produced when the actor wrote no delete files, or a lost/failed metadata write.","commonSituations":"Sinks with zero rows in an epoch producing empty metadata; failures persisting metadata to the state store before commit coordination reads it back.","solutions":["Skip conversion for SinkMetadata with metadata: None instead of attempting TryFrom","Ensure the DV merger actor always attaches Serialized metadata before handing results to the commit coordinator","Check for state-store write failures or epoch mismatches that dropped the metadata"],"exampleFix":"// before\nlet result = IcebergPositionDeleteCommitResult::try_from(&meta)?;\n// after\nif meta.metadata.is_none() {\n    return Ok(IcebergPositionDeleteCommitResult::default());\n}\nlet result = IcebergPositionDeleteCommitResult::try_from(&meta)?;","handlingStrategy":"validation","validationCode":"fn position_delete_meta_ready(meta: &SinkMetadata) -> bool {\n    matches!(meta.metadata, Some(Serialized(_)))\n}","typeGuard":"fn get_serialized<'a>(m: &'a SinkMetadata) -> Option<&'a SerializedMetadata> {\n    match &m.metadata { Some(Serialized(s)) => Some(s), None => None }\n}","tryCatchPattern":"let Some(Serialized(value)) = &meta.metadata else {\n    tracing::warn!(\"no dv merger metadata; skipping\");\n    return Ok(IcebergPositionDeleteCommitResult::default());\n};","preventionTips":["Check metadata presence before TryFrom; treat None as a no-op epoch","Ensure actors always attach metadata even for empty batches","Monitor state-store write failures that can drop metadata"],"tags":["rust","iceberg","empty-payload"],"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-23T08:17:48.524Z"}