{"record":{"id":"92180ca5df9076dc","repo":"risingwavelabs/risingwave","slug":"compaction-max-snapshots-num-must-be-greater-tha","errorCode":null,"errorMessage":"`compaction.max_snapshots_num` must be greater than 0","messagePattern":"`compaction\\.max_snapshots_num` must be greater than 0","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/iceberg/config.rs","lineNumber":643,"sourceCode":"            return Err(SinkError::Config(anyhow!(\n                \"`commit-checkpoint-interval` must be greater than 0\"\n            )));\n        }\n\n        if config.compaction_interval_sec == Some(0) {\n            return Err(SinkError::Config(anyhow!(\n                \"`compaction_interval_sec` must be greater than 0\"\n            )));\n        }\n\n        if config.trigger_snapshot_count == Some(0) {\n            return Err(SinkError::Config(anyhow!(\n                \"`compaction.trigger_snapshot_count` must be greater than 0\"\n            )));\n        }\n\n        if config.max_snapshots_num_before_compaction == Some(0) {\n            return Err(SinkError::Config(anyhow!(\n                \"`compaction.max_snapshots_num` must be greater than 0\"\n            )));\n        }\n\n        if config.small_files_threshold_mb == Some(0) {\n            return Err(SinkError::Config(anyhow!(\n                \"`compaction.small_files_threshold_mb` must be greater than 0\"\n            )));\n        }\n\n        if config.delete_files_count_threshold == Some(0) {\n            return Err(SinkError::Config(anyhow!(\n                \"`compaction.delete_files_count_threshold` must be greater than 0\"\n            )));\n        }\n\n        if config.target_file_size_mb == Some(0) {\n            return Err(SinkError::Config(anyhow!(","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/iceberg/config.rs#L625-L661","documentation":"Numeric option validation in IcebergSinkConfig::from_btreemap: the compaction option `compaction.max_snapshots_num` was set to 0, which is meaningless (it would compact after every snapshot). The guard rejects zero values during sink creation or ALTER; positive integers pass.","triggerScenarios":"CREATE SINK with `compaction.max_snapshots_num = 0` (option `max_snapshots_num_before_compaction`) in the WITH options.","commonSituations":"Zero used as a placeholder in automation; users expecting 0 to mean 'no snapshot limit'; misconfigured tuning attempts.","solutions":["Set `max_snapshots_num_before_compaction` to a positive integer, e.g. 100.","Remove the option to use the default retention threshold."],"exampleFix":"// before\nWITH (connector = 'iceberg', max_snapshots_num = 0)\n// after\nWITH (connector = 'iceberg', max_snapshots_num = 100)","handlingStrategy":"validation","validationCode":"if (opts.max_snapshots_num != null && Number(opts.max_snapshots_num) <= 0) {\n  throw new Error('`compaction.max_snapshots_num` must be greater than 0');\n}","typeGuard":"function isValidOptionalPositive(v) {\n  return v == null || (Number.isInteger(v) && v > 0);\n}","tryCatchPattern":"try {\n  await createIcebergSink(opts);\n} catch (e) {\n  if (String(e).includes('max_snapshots_num')) {\n    delete opts.max_snapshots_num;\n    return createIcebergSink(opts);\n  }\n  throw e;\n}","preventionTips":["Never emit compaction options with 0 values from templates.","Sanitize numeric inputs from config forms.","Prefer omitting options over sending placeholder values."],"tags":["iceberg","sink","config-validation","compaction"],"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-14T16:17:12.679Z"}