risingwavelabs/risingwave · error · SinkError::Config
HTTP sink only supports append-only mode
Error message
HTTP sink only supports append-only mode
What it means
Configuration rejection raised in HttpSink::from_btreemap: the HTTP sink can only write rows, never emit deletes or updates, so a sink whose declaration is not append-only (e.g. an upsert sink with a primary key) cannot be instantiated. It fires when the caller passes a non-append-only sink type while creating or altering an HTTP sink.
Source
Thrown at src/connector/src/sink/http.rs:80
pub fn from_btreemap(
values: BTreeMap<String, String>,
) -> Result<(Self, BTreeMap<String, String>)> {
// Extract header.* keys before serde parsing
let mut headers = BTreeMap::new();
let mut rest = BTreeMap::new();
for (k, v) in &values {
if let Some(header_name) = k.strip_prefix("header.") {
headers.insert(header_name.to_owned(), v.clone());
} else {
rest.insert(k.clone(), v.clone());
}
}
let config = serde_json::from_value::<HttpConfig>(serde_json::to_value(rest).unwrap())
.map_err(|e| SinkError::Config(anyhow!(e)))?;
if config.r#type != SINK_TYPE_APPEND_ONLY {
return Err(SinkError::Config(anyhow!(
"HTTP sink only supports append-only mode"
)));
}
Ok((config, headers))
}
}
#[derive(Clone, Debug)]
enum HttpUrl {
Static(reqwest::Url),
Dynamic { url_index: usize },
}
/// Validates the HTTP sink parameters and returns the sink so callers can use it directly without
/// re-parsing.
fn validate_http_sink(
is_append_only: bool,View on GitHub (pinned to 6469eb736d)
Solutions
- Set type='append-only' in the sink WITH options
- Ensure the backing stream/MV is append-only (no UPDATE/DELETE)
- Use a sink connector that supports upsert/debezium modes (e.g. JDBC/Kafka) if you need mutations
Example fix
// before WITH (connector='http', url='...', type='debezium') // after WITH (connector='http', url='...', type='append-only')
Defensive patterns
Strategy: validation
Validate before calling
// reject non-append-only types before sink creation
if let Some(t) = options.get("type") {
if t != "append-only" { return Err(format!("HTTP sink requires type='append-only', got '{t}'")); }
} Try / catch
match HttpSink::from_btreemap(&props, ...) {
Err(SinkError::Config(e)) if e.to_string().contains("append-only") => {
log::error!("HTTP sink configured over mutating stream: {e}");
}
r => r?,
} Prevention
- Always set type='append-only' explicitly for HTTP sinks
- Only sink from append-only MVs
- Use CDC-capable connectors when updates/deletes matter
When it happens
Trigger: `from_btreemap` parses HttpConfig whose `r#type` field does not equal SINK_TYPE_APPEND_ONLY (e.g. user set type='debezium' or an upsert variant).
Common situations: User configures an HTTP sink over a source with updates/deletes and sets type to something other than 'append-only'; copy-pasting sink configs from Kafka/Debezium examples.
Related errors
- {e}
- HTTP sink method must be POST or PUT, got '{method}'
- HTTP sink requires url option when schema has exactly 1 colu
- sink type unsupported: {}
- sink format unsupported: {}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/3be6398eae4c78ff.
Report an issue: GitHub.