{"record":{"id":"18f4ee6ac96f3831","repo":"risingwavelabs/risingwave","slug":"iceberg-sink-metadata-should-be-an-object","errorCode":null,"errorMessage":"iceberg sink metadata should be an object","messagePattern":"iceberg sink metadata should be an object","errorType":"exception","errorClass":"SinkError::Iceberg","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/commit.rs","lineNumber":77,"sourceCode":"}\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\n                .as_u64()\n                .ok_or_else(|| anyhow!(\"schema_id should be a u64\"))?;\n        } else {\n            bail!(\"iceberg sink metadata should have schema_id\");\n        }\n\n        let partition_spec_id;\n        if let Some(serde_json::Value::Number(value)) = values.remove(PARTITION_SPEC_ID) {\n            partition_spec_id = value\n                .as_u64()\n                .ok_or_else(|| anyhow!(\"partition_spec_id should be a u64\"))?;\n        } else {\n            bail!(\"iceberg sink metadata should have partition_spec_id\");","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/commit.rs#L59-L95","documentation":"`IcebergCommitResult::try_from_serialized_bytes` parses the sink metadata bytes as JSON and requires a top-level JSON object whose keys carry schema_id, partition spec, and data files. If the parsed JSON is an array, string, number, etc. instead of an object, it bails with this error.","triggerScenarios":"Committing an Iceberg sink whose serialized metadata bytes deserialize to a non-object JSON value — e.g. corrupted metadata bytes, wrong bytes passed (a different sink's metadata format), or a version where the metadata layout changed.","commonSituations":"Pointing the commit path at metadata produced by a different sink type or older RisingWave version; byte corruption in storage; manual edits to serialized metadata.","solutions":["Verify the metadata bytes belong to an Iceberg sink commit (object-shaped JSON with schema_id)","Check for RisingWave version mismatch between writer and reader of the metadata","Re-run the commit from intact metadata; recreate the sink if metadata is corrupted","Log the raw bytes (or their prefix) to confirm what is actually stored"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"let v: serde_json::Value = serde_json::from_slice(&bytes).context(\"Can't parse iceberg sink metadata\")?;\nif !v.is_object() {\n    return Err(\"iceberg sink metadata must be a JSON object\".into());\n}","typeGuard":"fn is_metadata_object(bytes: &[u8]) -> bool {\n    serde_json::from_slice::<serde_json::Value>(bytes)\n        .map(|v| v.is_object())\n        .unwrap_or(false)\n}","tryCatchPattern":"match IcebergCommitResult::try_from_serialized_bytes(&bytes) {\n    Err(e) if e.to_string().contains(\"should be an object\") => {\n        // inspect/corroborate stored bytes; likely wrong sink type or version mismatch\n    }\n    other => other?,\n}","preventionTips":["Only feed Iceberg sink metadata bytes into this deserializer","Keep writer and reader RisingWave versions aligned","Avoid manual edits to serialized metadata"],"tags":["sink","iceberg","json","metadata"],"backgroundTag":"unexpected-response-shape","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"}