dbt-labs/dbt-core · error

inconsistent state in unpark

Error message

inconsistent state in unpark

What it means

unpark sets the parker state to NOTIFIED via an atomic swap and expects one of the three legal values. Any other value means the state machine was corrupted, so the library panics instead of attempting to wake a thread in an undefined state. Like error 20, this is an internal invariant guard protecting the thread-parking synchronization protocol.

Source

Thrown at crates/dbt-runtime/src/park.rs:177

        match self.state.swap(EMPTY, SeqCst) {
            NOTIFIED => {} // got a notification, hurray!
            PARKED => {}   // no notification, alas
            n => panic!("inconsistent park_timeout state: {n}"),
        }
    }

    fn unpark(&self) {
        // To ensure the unparked thread will observe any writes we made before
        // this call, we must perform a release operation that `park` can
        // synchronize with. To do that we must write `NOTIFIED` even if `state`
        // is already `NOTIFIED`. That is why this must be a swap rather than a
        // compare-and-swap that returns if it reads `NOTIFIED` on failure.
        match self.state.swap(NOTIFIED, SeqCst) {
            EMPTY => return,    // no one was waiting
            NOTIFIED => return, // already unparked
            PARKED => {}        // gotta go wake someone up
            _ => panic!("inconsistent state in unpark"),
        }

        // There is a period between when the parked thread sets `state` to
        // `PARKED` (or last checked `state` in the case of a spurious wake
        // up) and when it actually waits on `cvar`. If we were to notify
        // during this period it would be ignored and then when the parked
        // thread went to sleep it would never wake up. Fortunately, it has
        // `lock` locked at this stage so we can acquire `lock` to wait until
        // it is ready to receive the notification.
        //
        // Releasing `lock` before the call to `notify_one` means that when the
        // parked thread wakes it doesn't get woken only to have to wait for us
        // to release `lock`.
        drop(self.mutex.lock().unwrap());

        self.condvar.notify_one();
    }
}

View on GitHub (pinned to 0267ce9170)

Solutions

  1. File a bug with dbt-runtime maintainers including the reproducer; a non-enum value here signals state-machine corruption
  2. Audit any unsafe code in your workspace that could write to the runtime's internal parker state
  3. Upgrade dbt-runtime to the latest release to pick up any fixes
  4. Run the workload under ThreadSanitizer or Miri in tests to locate the corrupting write
Defensive patterns

Strategy: try-catch

Try / catch

// unpark is internal; wrap if exposing custom scheduling
let result = std::panic::catch_unwind(|| parker.unpark());
if result.is_err() { /* treat as corruption; fail fast with diagnostics */ }

Prevention

When it happens

Trigger: unpark's swap(NOTIFIED, SeqCst) returns a value not in {EMPTY, NOTIFIED, PARKED} — only possible via out-of-band writes to the parker's state atomic (unsafe aliasing, corruption).

Common situations: Not hit in normal usage; appears when debugging concurrent runtimes, fuzzing unsafe code paths, or chasing memory corruption caused elsewhere in the process.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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