risingwavelabs/risingwave · error · SinkError::Http

unexpected url column type, expected varchar

Error message

unexpected url column type, expected varchar

What it means

At write time, `extract_url` reads the datum at the configured url column index and expects `ScalarRefImpl::Utf8`. If the datum is some other scalar variant (which should be impossible after validation, but can happen if schema changed or validation was bypassed), the row write fails with this SinkError::Http.

Source

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

                        Ok(url) => Ok(Some(url)),
                        Err(err) => {
                            tracing::warn!(
                                error = %err.as_report(),
                                payload = %self.strip_payload_for_log(row),
                                "skip HTTP sink row due to invalid URL in url column"
                            );
                            Ok(None)
                        }
                    }
                }
                Some(ScalarRefImpl::Utf8(_)) | None => {
                    tracing::warn!(
                        payload = %self.strip_payload_for_log(row),
                        "skip HTTP sink row due to null or empty url column"
                    );
                    Ok(None)
                }
                Some(_) => Err(SinkError::Http(anyhow!(
                    "unexpected url column type, expected varchar"
                ))),
            },
        }
    }

    fn strip_payload_for_log(&self, row: &impl Row) -> String {
        match row.datum_at(self.payload_index) {
            Some(ScalarRefImpl::Utf8(s)) => strip_text_payload(s),
            Some(ScalarRefImpl::Jsonb(j)) => strip_jsonb_payload(j),
            Some(_) => "<unexpected payload type>".to_owned(),
            None => "NULL".to_owned(),
        }
    }

    fn extract_payload(&self, row: &impl Row) -> Result<Option<String>> {
        Ok(match row.datum_at(self.payload_index) {
            Some(ScalarRefImpl::Utf8(s)) => Some(s.to_owned()),

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Recreate the sink so validation re-runs against the current schema
  2. Ensure the url column is and stays VARCHAR; cast upstream in the sink query
  3. Check whether the source schema changed since sink creation and fix the column type
Defensive patterns

Strategy: try-catch

Type guard

fn is_utf8(d: &ScalarRefImpl) -> bool { matches!(d, ScalarRefImpl::Utf8(_)) }

Try / catch

match res {
    Err(e) if e.to_string().contains("unexpected url column type") => {
        // schema drifted; recreate sink or fix url column type
    }
    other => other?,
}

Prevention

When it happens

Trigger: A row's `url` column datum is not `ScalarRefImpl::Utf8` during `write_chunk` -> `extract_url` — e.g. the source schema changed after the sink was created (column type altered), or an in-memory/Internal sink path feeds unexpected datum types.

Common situations: ALTER TABLE/TABLE type change after sink creation; streaming source with unstable schema delivering a non-string value into the url column; bugs in connector wiring passing wrong column index.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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