risingwavelabs/risingwave · error · SinkError
File sink only supports append-only mode at present. Please
Error message
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')`
What it means
The file sink currently only supports append-only streams; it cannot process UPDATE or DELETE events. During `validate`, if the sink's input is not append-only (`is_append_only == false`), creation is rejected with guidance to force append-only output via the encode option.
Source
Thrown at src/connector/src/sink/file_sink/opendal_sink.rs:153
/// A file is committed only once the batching strategy is met, so an untruncated barrier
/// would block the checkpoint forever on the non-decoupled in-memory log store.
fn is_sink_decouple(user_specified: &SinkDecouple) -> Result<bool> {
match user_specified {
SinkDecouple::Default | SinkDecouple::Enable => Ok(true),
SinkDecouple::Disable => Err(SinkError::Config(anyhow!(
"File sink can only be created with sink_decouple enabled. Please run `set sink_decouple = true` first."
))),
}
}
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()),View on GitHub (pinned to 6469eb736d)
Solutions
- Add `force_append_only = 'true'` to the ENCODE options, e.g. `FORMAT PLAIN ENCODE JSON(force_append_only = 'true')`
- Ensure the input stream is genuinely append-only (use an append-only MV or aggregation without a key)
- If updates must be preserved, use a non-file sink (e.g. JDBC/Kafka upsert) instead of a file sink
Example fix
// before CREATE SINK s FROM mv WITH (connector = 's3', type = 'append-only') FORMAT PLAIN ENCODE JSON; // after CREATE SINK s FROM mv WITH (connector = 's3', type = 'append-only') FORMAT PLAIN ENCODE JSON(force_append_only = 'true');
Defensive patterns
Strategy: validation
Validate before calling
-- only sink append-only MVs; or force append-only output: CREATE SINK s FROM mv WITH (connector = 's3', ...) FORMAT PLAIN ENCODE JSON(force_append_only = 'true');
Try / catch
match err {
e if e.to_string().contains("only supports append-only") => {
eprintln!("Add force_append_only = 'true' to ENCODE options, or use an append-only source");
}
other => return Err(other),
} Prevention
- Add `force_append_only = 'true'` whenever a file sink's input may receive updates
- Verify the source MV is append-only (no primary-key UPDATE/DELETE semantics) before creating a file sink
- Use upsert-capable sinks (Kafka, JDBC) when updates must be preserved
When it happens
Trigger: Creating a file sink from a materialized view/table or query that has upsert/delete semantics (primary key present with updates), without specifying `force_append_only = 'true'` in the encode options.
Common situations: Sinking a keyed MV that receives UPDATEs to a file sink; forgetting `force_append_only='true'` after FORMAT/ENCODE; migrating an upsert sink definition to a file sink.
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
- only append-only delta lake sink is supported
- File sink only supports `PARQUET` and `JSON` encode at prese
- No allow_alter_on_fly fields registered for sink: {sink_name
- Field '{field}' is not allowed to be altered on the fly for
- `commit_checkpoint_interval` must be greater than 0
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/cfbcf6f887747707.
Report an issue: GitHub.