{"record":{"id":"f3ef619b92517d28","repo":"risingwavelabs/risingwave","slug":"http-sink-requires-url-option-when-schema-has-exac","errorCode":null,"errorMessage":"HTTP sink requires url option when schema has exactly 1 column","messagePattern":"HTTP sink requires url option when schema has exactly 1 column","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/http.rs","lineNumber":127,"sourceCode":"            \"HTTP sink only supports append-only mode\"\n        )));\n    }\n\n    let method = match method {\n        None => reqwest::Method::POST,\n        Some(method) if method.eq_ignore_ascii_case(\"POST\") => reqwest::Method::POST,\n        Some(method) if method.eq_ignore_ascii_case(\"PUT\") => reqwest::Method::PUT,\n        Some(method) => {\n            return Err(SinkError::Config(anyhow!(\n                \"HTTP sink method must be POST or PUT, got '{method}'\"\n            )));\n        }\n    };\n\n    let fields = schema.fields();\n    let (payload_index, url, payload_type) = if fields.len() == 1 {\n        let Some(url) = url else {\n            return Err(SinkError::Config(anyhow!(\n                \"HTTP sink requires url option when schema has exactly 1 column\"\n            )));\n        };\n        let url = url\n            .parse()\n            .context(\"invalid URL\")\n            .map_err(SinkError::Config)?;\n        (0, HttpUrl::Static(url), fields[0].data_type.clone())\n    } else {\n        for field in fields {\n            match field.name.as_str() {\n                HTTP_SINK_PAYLOAD_COLUMN | HTTP_SINK_URL_COLUMN => {}\n                _ => {\n                    return Err(SinkError::Config(anyhow!(\n                        \"HTTP sink with multiple columns only supports payload and url columns, got {}\",\n                        field.name\n                    )));\n                }","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/http.rs#L109-L145","documentation":"When the sink schema has exactly one column, that column is treated as the payload and the target URL must come from the `url` option rather than a url column; if no `url` option was provided, configuration is invalid.","triggerScenarios":"`validate_http_sink` sees schema.fields().len() == 1 and url == None.","commonSituations":"Single-column payload MV without specifying url in WITH; user expected the single column to hold a URL but the engine treats it as payload.","solutions":["Add url='http://...' to the sink WITH options","Or add a second column named per the url-column convention so per-row URLs are used","Verify the schema of the streamed relation matches your intent"],"exampleFix":"// before\nCREATE SINK s FROM mv WITH (connector='http');\n// after\nCREATE SINK s FROM mv WITH (connector='http', url='http://example.com/hook');","handlingStrategy":"validation","validationCode":"// ensure single-column schemas carry a url option\nif schema.fields().len() == 1 && !options.contains_key(\"url\") {\n    return Err(\"single-column HTTP sink requires url option\".into());\n}","typeGuard":null,"tryCatchPattern":"match sink::try_create(props) {\n    Err(e) if e.to_string().contains(\"requires url option\") => {\n        log::error!(\"add url='...' to WITH clause: {e}\");\n    }\n    r => r?,\n}","preventionTips":["Always include url in HTTP sink WITH clauses","Explicitly project columns instead of SELECT *","Validate sink options in CI before applying migrations"],"tags":["http","sink","url","config","validation"],"backgroundTag":"missing-required-option","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"}