risingwavelabs/risingwave · error · SinkError

File sink only supports `PARQUET` and `JSON` encode at prese

Error message

File sink only supports `PARQUET` and `JSON` encode at present.

What it means

The file sink's `validate` restricts the encode format to PARQUET or JSON. If the sink's `format_desc.encode` is any other SinkEncode variant (e.g. Avro, Protobuf, Text, Bytes), creation is rejected because the file sink has no writer implementation for those formats.

Source

Thrown at src/connector/src/sink/file_sink/opendal_sink.rs:164

    async fn validate(&self) -> Result<()> {
        if matches!(self.engine_type, EngineType::Snowflake) {
            risingwave_common::license::Feature::SnowflakeSink
                .check_available()
                .map_err(|e| anyhow::anyhow!(e))?;
        }
        if !self.is_append_only {
            return Err(SinkError::Config(anyhow!(
                "File sink only supports append-only mode at present. \
                    Please change the query to append-only, and specify it \
                    explicitly after the `FORMAT ... ENCODE ...` statement. \
                    For example, `FORMAT xxx ENCODE xxx(force_append_only='true')`"
            )));
        }

        if self.format_desc.encode != SinkEncode::Parquet
            && self.format_desc.encode != SinkEncode::Json
        {
            return Err(SinkError::Config(anyhow!(
                "File sink only supports `PARQUET` and `JSON` encode at present."
            )));
        }

        match self.op.list(&self.path).await {
            Ok(_) => Ok(()),
            Err(e) => Err(anyhow!(e).into()),
        }
    }

    async fn new_log_sinker(
        &self,
        writer_param: crate::sink::SinkWriterParam,
    ) -> Result<Self::LogSinker> {
        let writer = OpenDalSinkWriter::new(
            self.op.clone(),
            &self.path,
            self.schema.clone(),

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Use `ENCODE JSON` (optionally with `force_append_only = 'true'`) or `ENCODE PARQUET` in the FORMAT...ENCODE clause
  2. If binary/schema-registry formats are required, use a Kafka sink instead of a file sink
  3. Check the resolved format_desc in your statement — ensure FORMAT matches a supported file-sink combination

Example fix

// before
CREATE SINK s FROM mv WITH (connector = 'gcs', ...)
FORMAT DEBEZIUM ENCODE AVRO;
// after
CREATE SINK s FROM mv WITH (connector = 'gcs', ...)
FORMAT PLAIN ENCODE JSON(force_append_only = 'true');
Defensive patterns

Strategy: validation

Validate before calling

let supported_encodes = ["json", "parquet"];
let encode = "json"; // value from your ENCODE clause
if !supported_encodes.contains(&encode.to_lowercase().as_str()) {
    return Err(format!("File sink supports only PARQUET and JSON, got {}", encode));
}

Type guard

fn is_file_sink_encode(e: &str) -> bool {
    matches!(e.to_uppercase().as_str(), "JSON" | "PARQUET")
}

Try / catch

match err {
    e if e.to_string().contains("PARQUET` and `JSON") => {
        eprintln!("Switch the ENCODE clause to JSON or PARQUET");
    }
    other => return Err(other),
}

Prevention

When it happens

Trigger: Creating a file sink whose FORMAT/ENCODE resolves to an encode other than PARQUET or JSON, e.g. `ENCODE AVRO`, `ENCODE PROTOBUF`, `ENCODE BYTES`, or an unset/unexpected encode in format_desc.

Common situations: Copying sink definitions from Kafka connectors that support Avro/Protobuf; assuming all encodes work for file sinks; typo or wrong FORMAT clause picked a different encode.

Related errors


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