{"record":{"id":"c6cda8881e1a1132","repo":"risingwavelabs/risingwave","slug":"partition-spec-id-should-be-a-u64","errorCode":null,"errorMessage":"partition_spec_id should be a u64","messagePattern":"partition_spec_id should be a u64","errorType":"exception","errorClass":"SinkError::Iceberg","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/commit.rs","lineNumber":93,"sourceCode":"            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\");\n        }\n\n        let data_files: Vec<SerializedDataFile>;\n        if let serde_json::Value::Array(values) = values\n            .remove(DATA_FILES)\n            .ok_or_else(|| anyhow!(\"iceberg sink metadata should have data_files object\"))?\n        {\n            data_files = values\n                .into_iter()\n                .map(from_value::<SerializedDataFile>)\n                .collect::<std::result::Result<_, _>>()\n                .unwrap();\n        } else {\n            bail!(\"iceberg sink metadata should have data_files object\");\n        }\n","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/commit.rs#L75-L111","documentation":"In try_from_serialized_bytes, the 'partition_spec_id' JSON field is matched as serde_json::Value::Number, then narrowed with as_u64(). If the value is a JSON number that is not representable as u64 (negative or fractional), this error fires. It enforces that partition_spec_id is a non-negative integer before it is cast to i32.","triggerScenarios":"Metadata JSON where 'partition_spec_id' is a negative integer (e.g. -1) or a float (e.g. 0.5); happens when metadata was produced by non-standard code or manually edited.","commonSituations":"Manually patched metadata in a debugging session, third-party tooling writing Iceberg sink metadata, corrupt values after storage truncation.","solutions":["Fix the metadata producer so partition_spec_id is serialized via serde_json::Value::Number from a i32/u32 value","Validate the raw JSON: partition_spec_id must be an integer >= 0 and <= i32::MAX (it is cast to i32 afterwards)","Replace the corrupted metadata entry with a freshly produced write result"],"exampleFix":"// before\n{\"schema_id\":1,\"partition_spec_id\":-1,\"data_files\":[]}\n// after\n{\"schema_id\":1,\"partition_spec_id\":0,\"data_files\":[]}","handlingStrategy":"validation","validationCode":"fn valid_partition_spec_id(bytes: &[u8]) -> bool {\n    serde_json::from_slice::<serde_json::Value>(bytes).ok()\n        .and_then(|v| v.get(\"partition_spec_id\").cloned())\n        .map_or(false, |v| v.as_u64().map_or(false, |n| n <= i32::MAX as u64))\n}","typeGuard":"fn as_nonneg_int(v: &serde_json::Value, key: &str) -> Option<i64> {\n    v.get(key)?.as_i64().filter(|n| *n >= 0)\n}","tryCatchPattern":"match try_from_serialized_bytes(&bytes) {\n    Ok(r) => r,\n    Err(e) => return Err(SinkError::Iceberg(anyhow!(\"invalid metadata: {}\", e.as_report()))),\n}","preventionTips":["Never hand-edit sink metadata JSON","Serialize ids from integer types, not floats or strings","Validate metadata shape in tests with round-trip serialize/deserialize"],"tags":["rust","iceberg","type-mismatch","json"],"backgroundTag":"invalid-argument-value","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"}