{"record":{"id":"f6fb162332656d24","repo":"tokio-rs/tokio","slug":"worker-threads-may-not-be-0","errorCode":null,"errorMessage":"`worker_threads` may not be 0.","messagePattern":"`worker_threads` may not be 0\\.","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"tokio-macros/src/entry.rs","lineNumber":140,"sourceCode":"        self.flavor = Some(runtime);\n        Ok(())\n    }\n\n    fn set_worker_threads(\n        &mut self,\n        worker_threads: syn::Lit,\n        span: Span,\n    ) -> Result<(), syn::Error> {\n        if self.worker_threads.is_some() {\n            return Err(syn::Error::new(\n                span,\n                \"`worker_threads` set multiple times.\",\n            ));\n        }\n\n        let worker_threads = parse_int(worker_threads, span, \"worker_threads\")?;\n        if worker_threads == 0 {\n            return Err(syn::Error::new(span, \"`worker_threads` may not be 0.\"));\n        }\n        self.worker_threads = Some((worker_threads, span));\n        Ok(())\n    }\n\n    fn set_start_paused(&mut self, start_paused: syn::Lit, span: Span) -> Result<(), syn::Error> {\n        if self.start_paused.is_some() {\n            return Err(syn::Error::new(span, \"`start_paused` set multiple times.\"));\n        }\n\n        let start_paused = parse_bool(start_paused, span, \"start_paused\")?;\n        self.start_paused = Some((start_paused, span));\n        Ok(())\n    }\n\n    fn set_crate_name(&mut self, name: syn::Lit, span: Span) -> Result<(), syn::Error> {\n        if self.crate_name.is_some() {\n            return Err(syn::Error::new(span, \"`crate` set multiple times.\"));","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/tokio-rs/tokio/blob/625954f365727668cb02d04172b34f1149637728/tokio-macros/src/entry.rs#L122-L158","documentation":"`set_worker_threads` (entry.rs:138) parses the value as `usize` and explicitly forbids zero, because a multi-threaded runtime needs at least one worker thread. Zero is nonsensical and would otherwise fail later at runtime builder construction; the macro fails early instead.","triggerScenarios":"Writing `#[tokio::main(worker_threads = 0)]`, or passing a computed value that resolves to 0.","commonSituations":"Driving `worker_threads` from an environment variable / config without clamping to a minimum of 1; miscounting available parallelism and subtracting one too many.","solutions":["Set `worker_threads` to at least 1 (commonly `std::thread::available_parallelism()`).","If deriving from configuration, clamp: `max(1, configured_value)`.","Omit the option to let tokio pick the default (number of CPU cores)."],"exampleFix":"// before\n#[tokio::main(worker_threads = 0)]\nasync fn main() {}\n\n// after — let tokio choose, or set a positive count\n#[tokio::main(flavor = \"multi_thread\", worker_threads = 4)]\nasync fn main() {}","handlingStrategy":"validation","validationCode":"// If deriving worker count from config, clamp before passing to a manual builder:\nlet n = config.worker_threads.unwrap_or_else(|| {\n    std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1)\n});\nlet n = std::cmp::max(1, n);\n// Note: the macro requires a literal, so use this only with the runtime builder API.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use a positive integer for `worker_threads`.","When computing a count, clamp with `max(1, value)`.","For dynamic counts, use `tokio::runtime::Builder` instead of the macro."],"tags":["tokio","macros","compile-error","config","invalid-value"],"backgroundTag":null,"analyzedSha":"625954f365727668cb02d04172b34f1149637728","analyzedAt":"2026-08-11T17:46:45.378Z","contentChangedAt":"2026-08-11T17:46:45.378Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}