risingwavelabs/risingwave · error · SinkError
ENCODE TEXT is only valid as key encode.
Error message
ENCODE TEXT is only valid as key encode.
What it means
The generic sink formatter dispatcher only allows ENCODE TEXT to serve as the KEY encoding (for key-only scenarios). When TEXT is chosen as the value encode for an AppendOnly or Upsert sink, it rejects the combination with this configuration error, because value serialization as plain text is not supported.
Source
Thrown at src/connector/src/sink/formatter/mod.rs:579
(F::Upsert, E::Avro, Some(E::Text)) => Impl::UpsertTextAvro(build(p).await?),
(F::Upsert, E::Avro, Some(E::Bytes)) => {
Impl::UpsertBytesAvro(build(p).await?)
}
(F::Upsert, E::Avro, None) => Impl::UpsertAvro(build(p).await?),
(F::Upsert, E::Protobuf, Some(E::Text)) => Impl::UpsertTextProto(build(p).await?),
(F::Upsert, E::Protobuf, Some(E::Bytes)) => {
Impl::UpsertBytesProto(build(p).await?)
}
(F::Upsert, E::Template, Some(E::Text)) => {
Impl::UpsertTextTemplate(build(p).await?)
}
(F::Upsert, E::Template, Some(E::Bytes)) => {
Impl::UpsertBytesTemplate(build(p).await?)
}
(F::Upsert, E::Template, None) => Impl::UpsertTemplate(build(p).await?),
(F::Debezium, E::Json, None) => Impl::DebeziumJson(build(p).await?),
(F::AppendOnly | F::Upsert, E::Text, _) => {
return Err(SinkError::Config(anyhow!(
"ENCODE TEXT is only valid as key encode."
)));
}
(F::AppendOnly, E::Avro, _)
| (F::Upsert, E::Protobuf, _)
| (F::Upsert, E::Bytes, _)
| (F::Debezium, E::Json, Some(_))
| (F::Debezium, E::Avro | E::Protobuf | E::Template | E::Text | E::Bytes, _)
| (_, E::Parquet, _)
| (_, _, Some(E::Parquet))
| (F::AppendOnly, E::Bytes, Some(_))
| (F::AppendOnly | F::Upsert, _, Some(E::Template) | Some(E::Json) | Some(E::Avro) | Some(E::Protobuf)) // reject other encode as key encode
=> {
return Err(SinkError::Config(anyhow!(
"sink format/encode/key_encode unsupported: {:?} {:?} {:?}",
format_desc.format,
format_desc.encode,
format_desc.key_encodeView on GitHub (pinned to 6469eb736d)
Solutions
- Move `ENCODE TEXT` to the key encode position (use `KEY ENCODE TEXT`) and pick a supported value encode such as JSON or Avro
- Use `ENCODE JSON` (or another supported encode) for the value if a full payload encode is needed
- Check the FORMAT...ENCODE...VALIDATE syntax in the RisingWave sink docs
Example fix
// before CREATE SINK s FROM mv WITH (connector='kafka', FORMAT APPEND ONLY ENCODE TEXT); // after CREATE SINK s FROM mv WITH (connector='kafka', FORMAT APPEND ONLY ENCODE JSON KEY ENCODE TEXT);
Defensive patterns
Strategy: validation
Validate before calling
fn validate_format(format: &str, encode: &str, key_encode: Option<&str>) -> Result<(), String> {
if encode.eq_ignore_ascii_case("text") {
return Err("ENCODE TEXT is only valid as key encode".into());
}
Ok(())
} Prevention
- Remember TEXT encode is key-only; always pair it with a value encode like JSON
- Test sink DDL on a dev cluster before applying to production
- Keep a template of valid FORMAT...ENCODE...KEY ENCODE combinations
When it happens
Trigger: Running `CREATE SINK ... FORMAT ... ENCODE TEXT` (or with an explicit key_encode) for AppendOnly/Upsert formats where TEXT lands in the value encode slot rather than the key encode slot.
Common situations: Users copying a key-only sink example and applying `ENCODE TEXT` at the value position; confusion between `key_encode` and `encode` options in the sink definition.
Related errors
- sink encode unsupported: {}
- sink format/encode/key_encode unsupported: {:?} {:?} {:?}
- sink type unsupported: {}
- sink format unsupported: {}
- unsupported {} as sink key encode
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/a80403ae7caa91ed.
Report an issue: GitHub.