risingwavelabs/risingwave · error
invalid Iceberg snapshot timestamp
Error message
invalid Iceberg snapshot timestamp
What it means
When scanning the iceberg_snapshots metadata table, each snapshot's timestamp_ms is converted to a Timestamptz; a None result (invalid milliseconds) aborts the scan with this error rather than emitting a row with a NULL committed_at.
Solutions
- Inspect the table's metadata JSON (v*.metadata.json) for snapshots with invalid 'timestamp-ms'
- Repair or regenerate the metadata from a valid snapshot/backup
- Query other metadata tables or snapshot history via Iceberg tools to locate the bad snapshot
Defensive patterns
Strategy: try-catch
Validate before calling
let ts_ok = snapshots.iter().all(|s| Timestamptz::from_millis(s.timestamp_ms()).is_some());
Try / catch
match result {
Err(e) if e.to_string().contains("invalid Iceberg snapshot timestamp") => {
// skip or repair the offending snapshot metadata
}
other => other?,
} Prevention
- Do not hand-edit Iceberg metadata JSON
- Use spec-compliant writers for snapshots
When it happens
Trigger: Querying the snapshot metadata table of an Iceberg table whose metadata contains a snapshot with a timestamp_ms value that cannot produce a valid Timestamptz (out of range millis).
Common situations: Corrupted or hand-edited Iceberg metadata JSON, or snapshots written by a buggy external writer with out-of-range timestamps.
Related errors
- Can't create iceberg sink write result from empty data!
- Can't find schema by id
- Fail to convert version_hint from utf8 to string
- Iceberg value exceeds BIGINT
- Iceberg value exceeds INTEGER
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/eaba4f1be786e0d3.
Report an issue: GitHub.
Appendix: source
Thrown at src/connector/src/sink/iceberg/metadata.rs:155
) -> ConnectorResult<Option<DataChunk>> {
Ok(builder.append_one_row(row.into_owned_row()))
}
/// Read one Iceberg metadata relation and emit bounded [`DataChunk`]s.
#[try_stream(ok = DataChunk, error = ConnectorError)]
pub async fn scan_iceberg_metadata(
table: Table,
metadata_type: IcebergMetadataTableType,
time_travel_info: Option<IcebergTimeTravelInfo>,
chunk_size: usize,
) {
let mut builder = DataChunkBuilder::new(metadata_type.schema().data_types(), chunk_size);
match metadata_type {
IcebergMetadataTableType::Snapshots => {
for snapshot in table.metadata().snapshots() {
let committed_at = Timestamptz::from_millis(snapshot.timestamp_ms())
.ok_or_else(|| anyhow!("invalid Iceberg snapshot timestamp"))?;
let summary =
serde_json::to_value(&snapshot.summary().additional_properties)?.into();
let row = IcebergSnapshotRow {
committed_at,
snapshot_id: snapshot.snapshot_id(),
parent_id: snapshot.parent_snapshot_id(),
sequence_number: snapshot.sequence_number(),
operation: snapshot.summary().operation.as_str().to_owned(),
manifest_list: snapshot.manifest_list().to_owned(),
summary,
};
if let Some(chunk) = append_row(&mut builder, row)? {
yield chunk;
}
}
}
IcebergMetadataTableType::Manifests | IcebergMetadataTableType::Files => {
let Some(snapshot_id) =View on GitHub (pinned to 6469eb736d)