risingwavelabs/risingwave · error · SinkError::Iceberg
Can't create iceberg sink write result from empty data!
Error message
Can't create iceberg sink write result from empty data!
What it means
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.
Source
Thrown at src/connector/src/sink/iceberg/commit.rs:64
use crate::connector_common::{IcebergCommittedSnapshot, IcebergSinkCompactionUpdate};
use crate::sink::catalog::SinkId;
use crate::sink::{Result, SinglePhaseCommitCoordinator, SinkParam, TwoPhaseCommitCoordinator};
const SCHEMA_ID: &str = "schema_id";
const PARTITION_SPEC_ID: &str = "partition_spec_id";
const DATA_FILES: &str = "data_files";
#[derive(Default, Clone)]
pub struct IcebergCommitResult {
pub schema_id: i32,
pub partition_spec_id: i32,
pub data_files: Vec<SerializedDataFile>,
}
impl IcebergCommitResult {
pub fn try_from(value: &SinkMetadata) -> Result<Self> {
let Some(Serialized(value)) = &value.metadata else {
bail!("Can't create iceberg sink write result from empty data!");
};
Self::try_from_serialized_bytes(&value.metadata)
}
pub fn try_from_serialized_bytes(value: &[u8]) -> Result<Self> {
let mut values = if let serde_json::Value::Object(value) =
serde_json::from_slice::<serde_json::Value>(value)
.context("Can't parse iceberg sink metadata")?
{
value
} else {
bail!("iceberg sink metadata should be an object");
};
let schema_id;
if let Some(serde_json::Value::Number(value)) = values.remove(SCHEMA_ID) {
schema_id = valueView on GitHub (pinned to 6469eb736d)
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
Defensive patterns
Strategy: try-catch
Validate before calling
// guard before calling IcebergCommitResult::try_from
if !matches!(meta.metadata, Some(Serialized(_))) {
// handle empty-metadata epoch explicitly
return Ok(IcebergCommitResult::default());
} Type guard
fn has_serialized_metadata(m: &SinkMetadata) -> bool {
matches!(m.metadata, Some(Serialized(_)))
} Try / catch
let res = IcebergCommitResult::try_from(&meta);
if let Err(e) = &res {
if e.to_string().contains("from empty data") {
// treat as no-op commit or alert on missing metadata
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- iceberg sink metadata should be an object
- schema_id should be a u64
- partition spec {} not found
- Fail to convert version_hint from utf8 to string: {}
- Can't clone request
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/378603c5154a70a8.
Report an issue: GitHub.