{"record":{"id":"10cb6efb70f177aa","repo":"risingwavelabs/risingwave","slug":"turbopuffer-namespace-must-be-1-to-128-bytes","errorCode":null,"errorMessage":"Turbopuffer namespace must be 1 to 128 bytes","messagePattern":"Turbopuffer namespace must be 1 to 128 bytes","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/turbopuffer.rs","lineNumber":726,"sourceCode":"            CompactedOp::Delete => deletes.push(id),\n        }\n    }\n    (upsert_rows, deletes)\n}\n\nfn document_id_from_i64(value: i64) -> DocumentId {\n    if value < 0 {\n        tracing::warn!(\n            value,\n            \"cast negative turbopuffer integer document id to unsigned integer\"\n        );\n    }\n    DocumentId::U64(value as u64)\n}\n\nfn validate_namespace(namespace: &str) -> Result<()> {\n    if namespace.is_empty() || namespace.len() > 128 {\n        return Err(SinkError::Config(anyhow!(\n            \"Turbopuffer namespace must be 1 to 128 bytes\"\n        )));\n    }\n    if !namespace\n        .bytes()\n        .all(|b| b.is_ascii_alphanumeric() || matches!(b, b'-' | b'_' | b'.'))\n    {\n        return Err(SinkError::Config(anyhow!(\n            \"Turbopuffer namespace must match [A-Za-z0-9-_.]{{1,128}}\"\n        )));\n    }\n    Ok(())\n}\n\nfn parse_column_selection(\n    value: Option<&str>,\n    schema: &Schema,\n    attribute_indices: &[usize],","sourceCodeStart":708,"sourceCodeEnd":744,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/turbopuffer.rs#L708-L744","documentation":"Turbopuffer namespace names must be between 1 and 128 bytes. validate_namespace enforces this before the sink builds the request URL or validates the connector config (try_from). A non-conforming namespace value in the WITH clause, or in the namespace_column data of a row, raises this error.","triggerScenarios":"Setting turbopuffer.namespace to an empty string or a string longer than 128 bytes in the sink WITH options; or a row whose namespace_column value is empty or exceeds 128 bytes, evaluated by url_for_row at write time.","commonSituations":"Copy-pasting a namespace with trailing whitespace stripped to empty; generating namespaces from data where some values are empty strings; very long auto-generated namespace names.","solutions":["Set turbopuffer.namespace to a 1–128 byte string in the WITH clause.","Clean the namespace_column data so values are non-empty and ≤128 bytes.","If namespaces come from a column, filter out rows with empty/too-long values before sinking."],"exampleFix":"// before\nWITH (connector='turbopuffer', turbopuffer.namespace='', ...)\n// after\nWITH (connector='turbopuffer', turbopuffer.namespace='my-index-v1', ...)","handlingStrategy":"validation","validationCode":"fn namespace_len_ok(ns: &str) -> bool {\n    !ns.is_empty() && ns.len() <= 128\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate namespace values (length 1–128) before CREATE SINK.","Filter empty namespace_column values upstream.","Avoid unbounded auto-generated namespace names."],"tags":["turbopuffer","namespace","validation","sink"],"backgroundTag":"value-out-of-range","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}