{"record":{"id":"b476d350c7072891","repo":"dbt-labs/dbt-core","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":"crates/dbt-runtime-macros/src/entry.rs","lineNumber":152,"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":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-runtime-macros/src/entry.rs#L134-L170","documentation":"After parsing `worker_threads` as an integer, the macro rejects a value of 0 because a multi-thread runtime must have at least one worker thread; tokio's Builder would panic or misbehave with zero workers, so the macro fails at compile time instead. The check lives in set_worker_threads right after parse_int.","triggerScenarios":"#[tokio::main(flavor = \"multi_thread\", worker_threads = 0)] — or any expression that parses to 0 via parse_int, such as worker_threads = 0x0.","commonSituations":"Computing thread count from a constant that defaulted to 0; misunderstanding that worker_threads must be >= 1; template/config substitution inserting a placeholder 0.","solutions":["Set worker_threads to at least 1","Remove worker_threads to let tokio pick the number of available cores","If the count is derived, clamp it: worker_threads = value.max(1)"],"exampleFix":"// before\n#[tokio::main(flavor = \"multi_thread\", worker_threads = 0)]\nasync fn main() {}\n\n// after\n#[tokio::main(flavor = \"multi_thread\", worker_threads = 4)]\nasync fn main() {}","handlingStrategy":"validation","validationCode":"fn check_worker_threads(n: i64) -> Result<(), String> {\n    if n >= 1 { Ok(()) } else { Err(\"worker_threads must be >= 1\".into()) }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass computed values that could be 0 as worker_threads","Clamp derived thread counts with .max(1) in your constant definitions","Omit worker_threads to let tokio size the pool automatically"],"tags":["rust","proc-macro","tokio","validation"],"backgroundTag":"argument-out-of-range","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}