risingwavelabs/risingwave · error · SinkError::Config

Turbopuffer sink can only be created with sink_decouple enab

Error message

Turbopuffer sink can only be created with sink_decouple enabled

What it means

The Turbopuffer connector only implements an async (decoupled) log sinker, so it can only run with sink decoupling enabled. In `is_sink_decouple`, `sink_decouple = false` (SinkDecouple::Disable) returns a config error instead of falling back to a sync path that does not exist.

Source

Thrown at src/connector/src/sink/turbopuffer.rs:279

        })
    }
}

impl Sink for TurbopufferSink {
    type LogSinker = TurbopufferLogSinker;

    const SINK_NAME: &'static str = TURBOPUFFER_SINK;

    crate::impl_validate_sink_unknown_fields!();

    async fn validate(&self) -> Result<()> {
        Ok(())
    }

    fn is_sink_decouple(user_specified: &SinkDecouple) -> Result<bool> {
        match user_specified {
            SinkDecouple::Default | SinkDecouple::Enable => Ok(true),
            SinkDecouple::Disable => Err(SinkError::Config(anyhow!(
                "Turbopuffer sink can only be created with sink_decouple enabled"
            ))),
        }
    }

    async fn new_log_sinker(&self, writer_param: SinkWriterParam) -> Result<Self::LogSinker> {
        let write_batch_size = self.config.write_batch_size;
        let max_linger = Duration::from_secs(self.config.max_linger_second);
        let writer = TurbopufferSinkWriter::new(
            self.config.clone(),
            self.schema.clone(),
            self.pk_index,
            self.namespace.clone(),
            self.attribute_indices.clone(),
            self.generated_schema.clone(),
            write_batch_size,
            max_linger,
        )?;

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Remove the `sink_decouple` option entirely so the default (enabled) applies.
  2. Explicitly set `sink_decouple = true` in the WITH options.
  3. Check cluster-level sink decouple defaults if you expected it to be on.

Example fix

// before
WITH (connector='turbopuffer', namespace='docs', sink_decouple=false);

// after
WITH (connector='turbopuffer', namespace='docs', sink_decouple=true);
Defensive patterns

Strategy: validation

Validate before calling

if (withClause.sink_decouple === false || withClause.sink_decouple === 'disable') {
  throw new Error('turbopuffer sink requires sink_decouple enabled');
}

Prevention

When it happens

Trigger: Creating a Turbopuffer sink with `WITH (sink_decouple = false)` or `sink_decouple = 'disable'`.

Common situations: Users disabling decouple to try to lower end-to-end latency or for debugging, copying sink templates that set sink_decouple = false, environments where decouple was globally defaulted off and the user pinned it off.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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