{"record":{"id":"edf9a9586d07c74e","repo":"risingwavelabs/risingwave","slug":"e-edf9a9","errorCode":null,"errorMessage":"{e}","messagePattern":"\\{e\\}","errorType":"validation","errorClass":"SinkError","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/file_sink/webhdfs.rs","lineNumber":87,"sourceCode":"pub struct WebhdfsSink;\n\nimpl UnknownFields for WebhdfsConfig {\n    fn unknown_fields(&self) -> HashMap<String, String> {\n        self.unknown_fields.clone()\n    }\n}\n\ncrate::impl_sink_unknown_fields!(WebhdfsConfig);\n\nimpl OpendalSinkBackend for WebhdfsSink {\n    type Properties = WebhdfsConfig;\n\n    const SINK_NAME: &'static str = WEBHDFS_SINK;\n\n    fn from_btreemap(btree_map: BTreeMap<String, String>) -> Result<Self::Properties> {\n        let config =\n            serde_json::from_value::<WebhdfsConfig>(serde_json::to_value(btree_map).unwrap())\n                .map_err(|e| SinkError::Config(anyhow!(e)))?;\n        if config.r#type != SINK_TYPE_APPEND_ONLY && config.r#type != SINK_TYPE_UPSERT {\n            return Err(SinkError::Config(anyhow!(\n                \"`{}` must be {}, or {}\",\n                SINK_TYPE_OPTION,\n                SINK_TYPE_APPEND_ONLY,\n                SINK_TYPE_UPSERT\n            )));\n        }\n        Ok(config)\n    }\n\n    fn new_operator(properties: WebhdfsConfig) -> Result<Operator> {\n        FileSink::<WebhdfsSink>::new_webhdfs_sink(properties)\n    }\n\n    fn get_path(properties: Self::Properties) -> String {\n        properties.common.path\n    }","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/file_sink/webhdfs.rs#L69-L105","documentation":"`WebhdfsConfig::from_btreemap` converts the sink WITH-options into `WebhdfsConfig` via serde JSON round-trip; deserialization failures are converted into this Config error with the serde message embedded.","triggerScenarios":"`CREATE SINK ... WITH (connector='webhdfs', ...)` where an option fails serde deserialization into WebhdfsConfig — e.g. malformed `webhdfs.host`, bad boolean/int strings, or unexpected characters in URL-ish fields.","commonSituations":"Wrong HDFS host/port formats, shell quoting stripping or adding characters, config struct evolution making previously valid properties invalid.","solutions":["Read the serde message to identify the bad option and correct its value","Compare each option against the WebhdfsConfig field types","Test the WebHDFS endpoint URL separately (curl to NameNode) to rule out malformed URLs"],"exampleFix":"// before\nWITH (connector='webhdfs', webhdfs.host='hdfs://namenode:9870')\n// after\nWITH (connector='webhdfs', webhdfs.host='namenode', webdfs_port=9870)","handlingStrategy":"validation","validationCode":"// Validate WebHDFS options pre-flight\nconst webhdfsOpts = { 'webhdfs.host': 'namenode', path: 'out/' };\nfor (const [k, v] of Object.entries(webhdfsOpts)) {\n  if (typeof v !== 'string' || v.trim() === '') throw new Error(`invalid ${k}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep host/port as separate well-formed values","Check WebHDFSConfig docs for expected field formats","Quote WITH values carefully in shell scripts"],"tags":["serde","config","webhdfs","sink"],"backgroundTag":"schema-validation-failed","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"}