risingwavelabs/risingwave · error · SinkError::Config

HTTP sink with multiple columns only supports payload and…

Error message

HTTP sink with multiple columns only supports payload and url columns, got {}

What it means

Schema validation in validate_http_sink: when the sink schema has more than one column, every column must be named `payload` or `url`; any other column name triggers this error. It names the offending column so the user can rename or drop it.

Solutions

  1. Restrict the MV to only payload and url columns (project explicitly in SELECT)
  2. Rename your columns to the expected payload/url column names
  3. Collapse extra data into the payload column (e.g. JSON-encode it)

Example fix

// before
CREATE MATERIALIZED VIEW mv AS SELECT payload, url, extra_meta FROM src;
// after
CREATE MATERIALIZED VIEW mv AS SELECT payload, url FROM src;
Defensive patterns

Strategy: validation

Validate before calling

// verify only allowed columns exist for multi-column schemas
let allowed: Vec<&str> = vec!["payload", "url"]; // per HTTP_SINK_* constants
let names: Vec<&str> = schema.fields().iter().map(|f| f.name.as_str()).collect();
if names.len() > 1 && names.iter().any(|n| !allowed.contains(n)) {
    return Err(format!("unsupported columns: only payload/url allowed, got {names:?}"));
}

Try / catch

match sink::try_create(props) {
    Err(e) if e.to_string().contains("payload and url columns") => {
        log::error!("project the MV down to payload/url columns: {e}");
    }
    r => r?,
}

Prevention

When it happens

Trigger: `validate_http_sink` iterates multi-column fields and finds a name that is neither HTTP_SINK_PAYLOAD_COLUMN nor HTTP_SINK_URL_COLUMN.

Common situations: User tries to send extra metadata columns alongside the payload; schema of the MV inherited extra columns from SELECT *; renamed payload/url columns.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/19706960a85d5ee6. Report an issue: GitHub.

Appendix: source

Thrown at src/connector/src/sink/http.rs:141

    let fields = schema.fields();
    let (payload_index, url, payload_type) = if fields.len() == 1 {
        let Some(url) = url else {
            return Err(SinkError::Config(anyhow!(
                "HTTP sink requires url option when schema has exactly 1 column"
            )));
        };
        let url = url
            .parse()
            .context("invalid URL")
            .map_err(SinkError::Config)?;
        (0, HttpUrl::Static(url), fields[0].data_type.clone())
    } else {
        for field in fields {
            match field.name.as_str() {
                HTTP_SINK_PAYLOAD_COLUMN | HTTP_SINK_URL_COLUMN => {}
                _ => {
                    return Err(SinkError::Config(anyhow!(
                        "HTTP sink with multiple columns only supports payload and url columns, got {}",
                        field.name
                    )));
                }
            }
        }

        let payload_index = fields
            .iter()
            .position(|field| field.name == HTTP_SINK_PAYLOAD_COLUMN)
            .ok_or_else(|| {
                SinkError::Config(anyhow!(
                    "HTTP sink with multiple columns requires a payload column"
                ))
            })?;
        let url_index = fields
            .iter()
            .position(|field| field.name == HTTP_SINK_URL_COLUMN);

View on GitHub (pinned to 6469eb736d)