risingwavelabs/risingwave · error · SinkError
The key encode is TEXT, but the primary key column {} has ty
Error message
The key encode is TEXT, but the primary key column {} has type {}. The key encode TEXT requires the primary key column to be of type varchar, bool, small int, int, big int, serial or rw_int256. What it means
When key encode is TEXT, the primary key column must be one of the textual/integral types (varchar, bool, smallint, int, bigint, serial, int256) because the encoder renders it as a UTF-8 string. Floats and other types are deliberately rejected (see PR #16377 discussion on ambiguity of float key rendering).
Source
Thrown at src/connector/src/sink/formatter/mod.rs:270
}
}
}
}
impl EncoderBuild for TextEncoder {
async fn build(params: EncoderParams<'_>, pk_indices: Option<Vec<usize>>) -> Result<Self> {
let (pk_index, schema_ref) = ensure_only_one_pk("TEXT", ¶ms, &pk_indices)?;
match &schema_ref.data_type() {
DataType::Varchar
| DataType::Boolean
| DataType::Int16
| DataType::Int32
| DataType::Int64
| DataType::Int256
| DataType::Serial => {}
_ => {
// why we don't allow float as text for key encode: https://github.com/risingwavelabs/risingwave/pull/16377#discussion_r1591864960
return Err(SinkError::Config(anyhow!(
"The key encode is TEXT, but the primary key column {} has type {}. The key encode TEXT requires the primary key column to be of type varchar, bool, small int, int, big int, serial or rw_int256.",
schema_ref.name,
schema_ref.data_type
)));
}
}
Ok(Self::new(params.schema, pk_index))
}
}
impl EncoderBuild for AvroEncoder {
async fn build(b: EncoderParams<'_>, pk_indices: Option<Vec<usize>>) -> Result<Self> {
use crate::schema::{SchemaLoader, SchemaVersion};
let loader = SchemaLoader::from_format_options(b.topic, &b.format_desc.options)
.await
.map_err(|e| SinkError::Config(anyhow!(e)))?;View on GitHub (pinned to 6469eb736d)
Solutions
- Cast the key column to varchar in the sink query
- Restructure so the key is an integer or varchar column
- Use a binary key encode (e.g. AVRO) if the key must preserve non-textual types
Example fix
// before: t.ts is TIMESTAMP, key_encode='text' CREATE SINK s FROM t WITH (key_encode = 'text'); // after CREATE SINK s AS SELECT ts::varchar AS ts_key, * FROM t WITH (key_encode = 'text');
Defensive patterns
Strategy: validation
Validate before calling
const TEXT_KEY_TYPES: &[DataType] = &[Varchar, Boolean, Int16, Int32, Int64, Serial, Int256];
if key_encode == "text" && !TEXT_KEY_TYPES.contains(&pk_field.data_type) {
return Err("pk type not supported by text key encode");
} Type guard
fn supports_text_key(dt: &DataType) -> bool {
matches!(dt, DataType::Varchar | DataType::Boolean | DataType::Int16 | DataType::Int32 | DataType::Int64 | DataType::Serial | DataType::Int256)
} Prevention
- Keep text key encodes on varchar/int/bool keys
- Cast float/decimal/timestamp keys to varchar explicitly
When it happens
Trigger: KEY ENCODE TEXT configured while the single PK column resolves to an unsupported DataType (e.g. Float64, Decimal, Timestamp, Struct).
Common situations: Using a float or timestamp primary key with a Kafka text key; expecting decimal keys to round-trip losslessly.
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
- The key encode is BYTES, but the primary key column {} has t
- `{MEMBER_NAME}` must be set to `varchar` and `primary_key`
- Turbopuffer document id column must be an integer or varchar
- Primary key not defined for upsert bigquery sink (please def
- Primary key not defined for upsert clickhouse sink (please d
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/d1553cdaf8cd55b0.
Report an issue: GitHub.