{"record":{"id":"4e848b7c86734813","repo":"risingwavelabs/risingwave","slug":"turbopuffer-sink-requires-only-one-of-namespace-or","errorCode":null,"errorMessage":"Turbopuffer sink requires only one of namespace or namespace_column","messagePattern":"Turbopuffer sink requires only one of namespace or namespace_column","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/turbopuffer.rs","lineNumber":199,"sourceCode":"                    .fields()\n                    .iter()\n                    .position(|field| field.name == *namespace_column)\n                    .ok_or_else(|| {\n                        SinkError::Config(anyhow!(\n                            \"Turbopuffer namespace_column '{}' not found in sink schema\",\n                            namespace_column\n                        ))\n                    })?;\n                if schema[index].data_type != DataType::Varchar {\n                    return Err(SinkError::Config(anyhow!(\n                        \"Turbopuffer namespace_column must be varchar, got {:?}\",\n                        schema[index].data_type\n                    )));\n                }\n                TurbopufferNamespace::Dynamic { index }\n            }\n            (Some(_), Some(_)) => {\n                return Err(SinkError::Config(anyhow!(\n                    \"Turbopuffer sink requires only one of namespace or namespace_column\"\n                )));\n            }\n            (None, None) => {\n                return Err(SinkError::Config(anyhow!(\n                    \"Turbopuffer sink requires either namespace or namespace_column\"\n                )));\n            }\n        };\n\n        // Turbopuffer treats `id` as the document ID in write requests; it is not a schema\n        // attribute. Dynamic namespace is also metadata for routing, not a document attribute.\n        let excluded_indices = match &namespace {\n            TurbopufferNamespace::Static(_) => HashSet::from([pk_index]),\n            TurbopufferNamespace::Dynamic { index } => HashSet::from([pk_index, *index]),\n        };\n        let attribute_indices = (0..schema.len())\n            .filter(|idx| !excluded_indices.contains(idx))","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/turbopuffer.rs#L181-L217","documentation":"The Turbopuffer sink accepts the namespace either as a static literal (`namespace`) or dynamically per row (`namespace_column`), but not both. In `try_from`, the (Some, Some) arm of the namespace match rejects sinks that specify both options together.","triggerScenarios":"Creating a Turbopuffer sink whose WITH options include both `namespace = 'x'` and `namespace_column = 'col'`.","commonSituations":"Merging config snippets from two examples; adding namespace_column to an existing sink that already had a static namespace; templated sink definitions that inject both keys.","solutions":["Remove the `namespace` option and keep `namespace_column` if namespaces vary per row.","Remove the `namespace_column` option and keep the static `namespace` if one namespace is enough.","Review the final WITH clause with SHOW SINK / the catalog to ensure only one namespace option remains."],"exampleFix":"// before\nWITH (\n  connector = 'turbopuffer',\n  namespace = 'docs',\n  namespace_column = 'ns'\n)\n\n// after\nWITH (\n  connector = 'turbopuffer',\n  namespace_column = 'ns'\n)","handlingStrategy":"validation","validationCode":"// Ensure only one namespace option appears in the WITH clause\nconst opts = ['namespace', 'namespace_column'];\nif (opts.filter(o => withClause[o] != null).length > 1) throw new Error('specify only one of namespace / namespace_column');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat namespace and namespace_column as mutually exclusive in your sink tooling","Review the generated WITH clause before submitting CREATE SINK"],"tags":["sink","turbopuffer","config","conflicting-options"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}