{"record":{"id":"696a9cd5329237b1","repo":"influxdata/influxdb","slug":"num-row-groups-in-parallel-should-be-above-zero","errorCode":null,"errorMessage":"num_row_groups_in_parallel should be above zero","messagePattern":"num_row_groups_in_parallel should be above zero","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/parquet_file/src/storage.rs","lineNumber":247,"sourceCode":"            parquet_write_parallelization_settings: Default::default(),\n        }\n    }\n\n    /// Provide settings for parallelized writes. Settings determine the\n    /// amount of parallelization per row group and per column.\n    ///\n    /// # Panics\n    ///\n    /// This will panic if an invalid usize (not > 0) is used.\n    pub fn with_parallel_write_settings(\n        self,\n        num_row_group_writers: usize,\n        num_column_writers_across_row_groups: usize,\n    ) -> Self {\n        Self {\n            parquet_write_parallelization_settings: ParallelParquetWriterOptions::new(\n                NonZeroUsize::new(num_row_group_writers)\n                    .expect(\"num_row_groups_in_parallel should be above zero\"),\n                NonZeroUsize::new(num_column_writers_across_row_groups)\n                    .expect(\"num_columns_in_parallel should be above zero\"),\n            ),\n            ..self\n        }\n    }\n\n    /// Get underlying object store.\n    pub fn object_store(&self) -> &Arc<DynObjectStore> {\n        &self.object_store\n    }\n\n    /// Get ID.\n    pub fn id(&self) -> StorageId {\n        self.id\n    }\n\n    /// Fake DataFusion context for testing that contains this store","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/influxdata/influxdb/blob/d28e26e048401c53cbb98cf2d6ab0cf1e98048ca/core/parquet_file/src/storage.rs#L229-L265","documentation":"ParquetStorage::with_parallel_write_settings wraps its two usize arguments into NonZeroUsize via NonZeroUsize::new(..).expect(\"num_row_groups_in_parallel should be above zero\") (and a sibling expect for num_columns_in_parallel). Passing 0 for either argument makes NonZeroUsize::new return None and panics immediately; the # Panics doc section states this contract. It is a fail-fast config-validation panic at builder time, before any IO happens.","triggerScenarios":"Calling with_parallel_write_settings(0, n) or (n, 0); typical sources are CLI/env config parsed straight into usize where unset maps to 0, or computed parallelism like f64 rounding/truncation yielding 0 (e.g. cores*0.25 with 0-1 cores).","commonSituations":"Config plumbing that defaults parallelism to 0 when a knob is missing; formulas deriving row-group writer counts from table width (n_columns * factor) that floor to 0 for narrow tables; deployments on tiny containers reporting 1 CPU with a fractional multiplier.","solutions":["Pass a value >= 1 for both arguments; if deriving from a formula, clamp with .max(1).","Parse config as NonZeroUsize (or validate > 0 and reject the config at load time) so 0 never reaches the builder.","Round instead of truncate when converting fractional parallelism to usize.","Document/enforce a minimum in your settings layer (e.g. num_row_groups: NonZeroUsize in the config struct)."],"exampleFix":"// before\nlet storage = storage.with_parallel_write_settings(0, num_columns); // panics\n\n// after\nlet storage = storage.with_parallel_write_settings(num_row_groups.max(1), num_columns.max(1));","handlingStrategy":"validation","validationCode":"// validate config before building the storage\nlet num_row_groups = config.num_row_group_writers; // from CLI/env/file\nif num_row_groups == 0 || config.num_column_writers_across_row_groups == 0 {\n    return Err(\"parallel write settings must be >= 1\".into());\n}\nlet storage = storage.with_parallel_write_settings(num_row_groups, config.num_column_writers_across_row_groups);","typeGuard":"// carry NonZeroUsize through your config so 0 is unrepresentable\nfn parse_parallelism(raw: &str) -> Result<NonZeroUsize, String> {\n    raw.parse::<usize>()\n        .ok()\n        .and_then(NonZeroUsize::new)\n        .ok_or_else(|| format!(\"'{raw}' must be a positive integer\"))\n}","tryCatchPattern":null,"preventionTips":["Model counts as NonZeroUsize in config schemas (serde supports it directly).","Clamp computed parallelism with .max(1) instead of truncating fractional formulas to usize.","Fail config load with a clear message on zero parallelism instead of panicking inside the builder.","Read the builder's # Panics doc section before wiring raw config values into with_parallel_write_settings."],"tags":["rust","influxdb-iox","configuration","nonzero","parallelism","builder-validation","panic"],"backgroundTag":"zero-value-config","analyzedSha":"d28e26e048401c53cbb98cf2d6ab0cf1e98048ca","analyzedAt":"2026-08-16T19:53:34.623Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}