{"record":{"id":"024a0a39457ec877","repo":"risingwavelabs/risingwave","slug":"file-sink-can-only-be-created-with-sink-decouple-e","errorCode":null,"errorMessage":"File sink can only be created with sink_decouple enabled. Please run `set sink_decouple = true` first.","messagePattern":"File sink can only be created with sink_decouple enabled\\. Please run `set sink_decouple = true` first\\.","errorType":"validation","errorClass":"SinkError","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/file_sink/opendal_sink.rs","lineNumber":140,"sourceCode":"    Webhdfs,\n    Snowflake,\n}\n\nimpl<S: OpendalSinkBackend> Sink for FileSink<S> {\n    type LogSinker = BatchingLogSinker<OpenDalSinkWriter>;\n\n    const SINK_NAME: &'static str = S::SINK_NAME;\n\n    fn validate_unknown_fields(&self) -> Result<()> {\n        crate::sink::validate_sink_unknown_fields(&self.unknown_fields)\n    }\n\n    /// A file is committed only once the batching strategy is met, so an untruncated barrier\n    /// would block the checkpoint forever on the non-decoupled in-memory log store.\n    fn is_sink_decouple(user_specified: &SinkDecouple) -> Result<bool> {\n        match user_specified {\n            SinkDecouple::Default | SinkDecouple::Enable => Ok(true),\n            SinkDecouple::Disable => Err(SinkError::Config(anyhow!(\n                \"File sink can only be created with sink_decouple enabled. Please run `set sink_decouple = true` first.\"\n            ))),\n        }\n    }\n\n    async fn validate(&self) -> Result<()> {\n        if matches!(self.engine_type, EngineType::Snowflake) {\n            risingwave_common::license::Feature::SnowflakeSink\n                .check_available()\n                .map_err(|e| anyhow::anyhow!(e))?;\n        }\n        if !self.is_append_only {\n            return Err(SinkError::Config(anyhow!(\n                \"File sink only supports append-only mode at present. \\\n                    Please change the query to append-only, and specify it \\\n                    explicitly after the `FORMAT ... ENCODE ...` statement. \\\n                    For example, `FORMAT xxx ENCODE xxx(force_append_only='true')`\"\n            )));","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/file_sink/opendal_sink.rs#L122-L158","documentation":"File sinks buffer data and commit files only when the batching strategy is met, so they require decoupled sinks (checkpoint-driven commits on a durable log store). This function is a hard override for the `is_sink_decouple` trait hook: it forces decoupling on by default but explicitly rejects a user who sets `sink_decouple = false`, because without decoupling an untruncated barrier would block checkpoints forever on the in-memory log store.","triggerScenarios":"Creating a file sink (S3/GCS/Azure/FS opendal-based) with the WITH/SESSION option `sink_decouple = false` (or explicitly disabled), e.g. `CREATE SINK ... WITH (...) sink_decouple = false` or `SET sink_decouple = false` at session level.","commonSituations":"Users who disabled sink_decouple globally to test or debug other sinks, then create a file sink; copied session settings from a non-file sink setup; older workflows predating the decouple requirement.","solutions":["Remove the `sink_decouple = false` setting or set `sink_decouple = true` before creating the sink","Run `SET sink_decouple = true;` in the session, or reset it to default so the file sink override applies","Create the sink in a fresh session that does not carry a disabled sink_decouple setting"],"exampleFix":"// before\nSET sink_decouple = false;\nCREATE SINK s FROM mv WITH (connector = 's3', ...);\n// after\nSET sink_decouple = true;\nCREATE SINK s FROM mv WITH (connector = 's3', ...);","handlingStrategy":"validation","validationCode":"-- run before CREATE SINK\nSHOW sink_decouple;\n-- ensure it is not 'false'; if needed:\nSET sink_decouple = true;","typeGuard":null,"tryCatchPattern":"match err {\n    SinkError::Config(msg) if msg.contains(\"sink_decouple\") => {\n        // re-create the sink with sink_decouple = true\n    }\n    other => return Err(other),\n}","preventionTips":["Do not set sink_decouple = false globally or in sessions used for file sinks","Use default settings for file sinks — decoupling is forced and recommended","Add a comment to shared SQL scripts noting file sinks require sink_decouple"],"tags":["sink","file-sink","configuration","checkpointing"],"backgroundTag":"conflicting-config-options","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}