risingwavelabs/risingwave · error · SinkError::Config

Turbopuffer namespace_column

Error message

Turbopuffer namespace_column '{}' not found in sink schema

What it means

Raised in TryFrom<SinkParam> when namespace_column is set but no field with that name exists in the sink schema. The sink resolves the per-row namespace from this column, so a typo or a dropped/renamed column makes the namespace resolution fail and sink creation is aborted.

Solutions

  1. Correct namespace_column to match an existing VARCHAR column name exactly
  2. Add/derive a varchar namespace column in the upstream materialized view
  3. Remove namespace_column if a single fixed namespace via the namespace option suffices

Example fix

// before
WITH (connector='turbopuffer', namespace_column = 'tenant')  -- column is 'tenant_id'
// after
WITH (connector='turbopuffer', namespace_column = 'tenant_id')
Defensive patterns

Strategy: validation

Validate before calling

if (props.namespace_column && !schema.columns.some(c => c.name === props.namespace_column)) throw new Error('namespace_column not in schema')

Type guard

const hasColumn = (schema, name) => schema.columns?.some(c => c.name === name && c.type === 'Varchar');

Try / catch

catch (SinkError::Config(e)) if e.contains('namespace_column') { correct the column name and retry }

Prevention

When it happens

Trigger: CREATE SINK with connector='turbopuffer' and namespace_column='x' where the sink schema has no column literally named 'x' (typo, case mismatch, or column dropped upstream).

Common situations: Typo in column name; renamed column in the MV; case-sensitivity mismatch (e.g. 'Namespace' vs 'namespace').

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

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

                    "Turbopuffer document id column must be an integer or varchar, got {:?}",
                    data_type
                )));
            }
        };
        let config = TurbopufferConfig::from_btreemap(param.properties)?;

        let namespace = match (&config.namespace, &config.namespace_column) {
            (Some(namespace), None) => {
                validate_namespace(namespace)?;
                TurbopufferNamespace::Static(namespace.clone())
            }
            (None, Some(namespace_column)) => {
                let index = schema
                    .fields()
                    .iter()
                    .position(|field| field.name == *namespace_column)
                    .ok_or_else(|| {
                        SinkError::Config(anyhow!(
                            "Turbopuffer namespace_column '{}' not found in sink schema",
                            namespace_column
                        ))
                    })?;
                if schema[index].data_type != DataType::Varchar {
                    return Err(SinkError::Config(anyhow!(
                        "Turbopuffer namespace_column must be varchar, got {:?}",
                        schema[index].data_type
                    )));
                }
                TurbopufferNamespace::Dynamic { index }
            }
            (Some(_), Some(_)) => {
                return Err(SinkError::Config(anyhow!(
                    "Turbopuffer sink requires only one of namespace or namespace_column"
                )));
            }
            (None, None) => {

View on GitHub (pinned to 6469eb736d)