{"record":{"id":"774548162c8acda4","repo":"risingwavelabs/risingwave","slug":"num-shards-must-be-greater-than-0","errorCode":null,"errorMessage":"`num_shards` must be greater than 0","messagePattern":"`num_shards` must be greater than 0","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/turbopuffer.rs","lineNumber":112,"sourceCode":"\nimpl TurbopufferConfig {\n    fn from_btreemap(values: BTreeMap<String, String>) -> Result<Self> {\n        let config = serde_json::from_value::<TurbopufferConfig>(\n            serde_json::to_value(values).expect(\"serialize sink properties\"),\n        )\n        .map_err(|e| SinkError::Config(anyhow!(e)))?;\n        if config.write_batch_size == 0 {\n            return Err(SinkError::Config(anyhow!(\n                \"`write_batch_size` must be greater than 0\"\n            )));\n        }\n        if config.max_linger_second == 0 {\n            return Err(SinkError::Config(anyhow!(\n                \"`max_linger_second` must be greater than 0\"\n            )));\n        }\n        if config.num_shards == Some(0) {\n            return Err(SinkError::Config(anyhow!(\n                \"`num_shards` must be greater than 0\"\n            )));\n        }\n        Ok(config)\n    }\n}\n\n#[derive(Clone, Debug)]\nenum TurbopufferNamespace {\n    Static(String),\n    Dynamic { index: usize },\n}\n\n#[derive(Clone, Debug)]\npub struct TurbopufferSink {\n    config: TurbopufferConfig,\n    schema: Schema,\n    pk_index: usize,","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/turbopuffer.rs#L94-L130","documentation":"Validation guard in TurbopufferConfig::from_btreemap that rejects sink properties where num_shards is 0. The sink must write into at least one Turbopuffer shard; a zero value cannot be mapped to a valid namespace layout, so sink creation fails immediately with a config error.","triggerScenarios":"CREATE SINK with connector='turbopuffer' and WITH option num_shards = '0'.","commonSituations":"Placeholder 0 left in config; misunderstanding that omitting the option means unlimited/zero shards.","solutions":["Set num_shards to a positive integer","Remove num_shards to let the sink decide default sharding","Validate the value before creating the sink"],"exampleFix":"// before\nWITH (connector='turbopuffer', num_shards = '0')\n// after\nWITH (connector='turbopuffer', num_shards = '4')","handlingStrategy":"validation","validationCode":"if (props.num_shards !== undefined && Number(props.num_shards) <= 0) throw new Error('num_shards must be > 0')","typeGuard":"const validShards = (n) => Number.isInteger(n) && n > 0;","tryCatchPattern":"catch (SinkError::Config(e)) if e.contains('num_shards') { set positive shard count and retry }","preventionTips":["Omit num_shards to use sink defaults","Avoid 0 placeholders in config generators","Validate integer options before DDL"],"tags":["turbopuffer","config","validation","sharding"],"backgroundTag":"invalid-config-value","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"}