dbt-labs/dbt-core · error · syn::Error

`worker_threads` may not be 0.

Error message

`worker_threads` may not be 0.

What it means

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.

Source

Thrown at crates/dbt-runtime-macros/src/entry.rs:152

        self.flavor = Some(runtime);
        Ok(())
    }

    fn set_worker_threads(
        &mut self,
        worker_threads: syn::Lit,
        span: Span,
    ) -> Result<(), syn::Error> {
        if self.worker_threads.is_some() {
            return Err(syn::Error::new(
                span,
                "`worker_threads` set multiple times.",
            ));
        }

        let worker_threads = parse_int(worker_threads, span, "worker_threads")?;
        if worker_threads == 0 {
            return Err(syn::Error::new(span, "`worker_threads` may not be 0."));
        }
        self.worker_threads = Some((worker_threads, span));
        Ok(())
    }

    fn set_start_paused(&mut self, start_paused: syn::Lit, span: Span) -> Result<(), syn::Error> {
        if self.start_paused.is_some() {
            return Err(syn::Error::new(span, "`start_paused` set multiple times."));
        }

        let start_paused = parse_bool(start_paused, span, "start_paused")?;
        self.start_paused = Some((start_paused, span));
        Ok(())
    }

    fn set_crate_name(&mut self, name: syn::Lit, span: Span) -> Result<(), syn::Error> {
        if self.crate_name.is_some() {
            return Err(syn::Error::new(span, "`crate` set multiple times."));

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Set worker_threads to at least 1
  2. Remove worker_threads to let tokio pick the number of available cores
  3. If the count is derived, clamp it: worker_threads = value.max(1)

Example fix

// before
#[tokio::main(flavor = "multi_thread", worker_threads = 0)]
async fn main() {}

// after
#[tokio::main(flavor = "multi_thread", worker_threads = 4)]
async fn main() {}
Defensive patterns

Strategy: validation

Validate before calling

fn check_worker_threads(n: i64) -> Result<(), String> {
    if n >= 1 { Ok(()) } else { Err("worker_threads must be >= 1".into()) }
}

Prevention

When it happens

Trigger: #[tokio::main(flavor = "multi_thread", worker_threads = 0)] — or any expression that parses to 0 via parse_int, such as worker_threads = 0x0.

Common situations: Computing thread count from a constant that defaulted to 0; misunderstanding that worker_threads must be >= 1; template/config substitution inserting a placeholder 0.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/b476d350c7072891. Report an issue: GitHub.