risingwavelabs/risingwave · error

unsupported encoding for Upsert

Error message

unsupported encoding for Upsert

What it means

build_accessor_builder only supports Json, Protobuf, and Avro encodings for upsert sources. Any other EncodingProperties variant (e.g. Debezium AVRO-less encodings, Bytes, Maxwell, Canal native encodings) is rejected because upsert parsing requires a structured key/payload accessor those encodings cannot provide.

Source

Thrown at src/connector/src/parser/upsert_parser.rs:42

use crate::error::ConnectorResult;
use crate::parser::ParserFormat;
use crate::parser::unified::kv_event::KvEvent;
use crate::source::{SourceColumnDesc, SourceContext, SourceContextRef};

#[derive(Debug)]
pub struct UpsertParser {
    key_builder: AccessBuilderImpl,
    payload_builder: AccessBuilderImpl,
    pub(crate) rw_columns: Vec<SourceColumnDesc>,
    source_ctx: SourceContextRef,
}

async fn build_accessor_builder(config: EncodingProperties) -> ConnectorResult<AccessBuilderImpl> {
    match config {
        EncodingProperties::Json(_)
        | EncodingProperties::Protobuf(_)
        | EncodingProperties::Avro(_) => Ok(AccessBuilderImpl::new_default(config).await?),
        _ => bail!("unsupported encoding for Upsert"),
    }
}

pub fn get_key_column_name(columns: &[SourceColumnDesc]) -> Option<String> {
    columns.iter().find_map(|column| {
        if matches!(
            column.additional_column.column_type,
            Some(AdditionalColumnType::Key(_))
        ) {
            Some(column.name.clone())
        } else {
            None
        }
    })
}

impl UpsertParser {
    pub async fn new(

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Change the source DDL to use ENCODE JSON, ENCODE PROTOBUF, or ENCODE AVRO with FORMAT UPSERT/DEBEZIUM.
  2. If the encoding is genuinely supported upstream, add it to the match arm in build_accessor_builder in src/connector/src/parser/upsert_parser.rs.
  3. Verify with SHOW CREATE SOURCE / the docs which encodings the upsert parser supports.

Example fix

// before
CREATE SOURCE s (...) WITH (connector='kafka', ...) FORMAT UPSERT ENCODE BYTES;
// after
CREATE SOURCE s (...) WITH (connector='kafka', ...) FORMAT UPSERT ENCODE AVRO;
Defensive patterns

Strategy: validation

Validate before calling

const UPSERT_ENCODINGS: &[&str] = &["json", "protobuf", "avro"];
fn validate_upsert_encoding(encoding: &str) -> Result<(), String> {
    if UPSERT_ENCODINGS.contains(&encoding.to_ascii_lowercase().as_str()) {
        Ok(())
    } else {
        Err(format!("encoding '{encoding}' unsupported for UPSERT; use one of {UPSERT_ENCODINGS:?}"))
    }
}

Prevention

When it happens

Trigger: Creating an upsert source (CREATE SOURCE ... FORMAT ENCODE ... ) whose encoding type is not one of json/protobuf/avro; e.g. FORMAT PLAIN ENCODE BYTES with UPSERT, or a Debezium/native encoding not mapped to those three variants.

Common situations: Configuring a Kafka upsert source with BYTES or an unsupported encoding; copy-pasting a plain-format source DDL and adding UPSERT; version where some encodings were never wired into the upsert path.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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