risingwavelabs/risingwave · error · SinkError::Config

Turbopuffer schema option references unknown attribute…

Error message

Turbopuffer schema option references unknown attribute column '{}'

What it means

parse_column_selection parses options like turbopuffer.filterable or turbopuffer.full_text_search, which take a comma-separated list of column names, and validates each name against the sink's attribute columns. If a listed column does not exist among the sink's attributes, the sink config is rejected at creation time with this error.

Solutions

  1. Check the exact column names in the sink's schema and correct the option list.
  2. Remove stale/renamed columns from turbopuffer.filterable / turbopuffer.full_text_search.
  3. Do not list the primary key column in these options; it is mapped to the Turbopuffer document id automatically.

Example fix

// before
WITH (connector='turbopuffer', turbopuffer.filterable='catgory,ts')
// after (typo fixed)
WITH (connector='turbopuffer', turbopuffer.filterable='category,ts')
Defensive patterns

Strategy: validation

Validate before calling

-- confirm every listed column exists before CREATE SINK
-- SELECT name FROM rw_catalog.rw_columns WHERE relation_id = <sink_source_id>;
fn cols_exist(listed: &[&str], schema_cols: &[&str]) -> Vec<String> {
    listed.iter().filter(|c| !schema_cols.contains(c)).map(|c| c.to_string()).collect()
}

Prevention

When it happens

Trigger: Creating a Turbopuffer sink where turbopuffer.filterable='a,b' (or turbopuffer.full_text_search) mentions a column name that is not one of the table's attribute columns — typically a typo, a column dropped/renamed in the source, or the primary key/id column which is not an attribute.

Common situations: Renaming columns in the upstream table without updating the sink WITH options; typos in the comma-separated list; assuming the primary key column can be marked filterable (it is handled separately as the document id).

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

        .collect::<HashSet<_>>();
    let columns: HashSet<String> = match value {
        Some(value) if value.trim() == "*" => {
            return Ok(attribute_names
                .into_iter()
                .map(str::to_owned)
                .collect::<HashSet<_>>());
        }
        Some(value) => value
            .split(',')
            .map(str::trim)
            .filter(|name| !name.is_empty())
            .map(str::to_owned)
            .collect(),
        None => return Ok(HashSet::new()),
    };
    for column in &columns {
        if !attribute_names.contains(column.as_str()) {
            return Err(SinkError::Config(anyhow!(
                "Turbopuffer schema option references unknown attribute column '{}'",
                column
            )));
        }
    }
    Ok(columns)
}

fn build_turbopuffer_schema(
    schema: &Schema,
    attribute_indices: &[usize],
    full_text_search_columns: &HashSet<String>,
    filterable_columns: &HashSet<String>,
) -> Result<Value> {
    let mut result = Map::new();
    for index in attribute_indices {
        let field = &schema[*index];
        let mut config = Map::new();

View on GitHub (pinned to 6469eb736d)