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
- Check the exact column names in the sink's schema and correct the option list.
- Remove stale/renamed columns from turbopuffer.filterable / turbopuffer.full_text_search.
- 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
- Copy column names directly from the table schema, not from memory.
- Update sink WITH options whenever upstream columns are renamed or dropped.
- Don't list the primary key in filterable/full_text_search — it's the doc id.
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
- Cannot find
- Cannot find
- Turbopuffer attribute column must not be named id
- Turbopuffer namespace_column must be varchar, got
- Turbopuffer namespace_column
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)