rayon-rs/rayon · error

owner thread

Error message

owner thread

What it means

Assertion failure inside Latch::wait in rayon-core. The wait method takes an Option<&WorkerThread>; when the latch kind is CountLatchKind::Stealing (a stealing-based count latch), waiting requires knowledge of the current worker thread to verify latch ownership and registry identity. The code calls owner.expect("owner thread"), so passing None with a stealing latch panics. It is an internal invariant guard, not user-input validation: callers such as broadcast_in must supply Some(worker_thread) whenever a stealing latch is in use. A None owner reaching this path indicates an API misuse inside the thread pool's synchronization machinery.

Solutions

  1. Ensure `broadcast`/`broadcast_in` is called from an allowed thread context per its docs (owner thread present)
  2. Use `install(pool, ...)` or run inside the pool's scope so an owner thread is available
  3. Prefer `join`/`scope` APIs which don't require the broadcast latch path
  4. Upgrade rayon-core; guard assertions around latch ownership have evolved

Example fix

// before
pool.broadcast(|ctx| ...); // from arbitrary thread hitting latch path
// after
pool.install(|| {
    pool.broadcast(|ctx| ...);
});
Defensive patterns

Strategy: try-catch

Try / catch

catch_unwind(AssertUnwindSafe(|| pool.broadcast(|ctx| ...)))

Prevention

When it happens

Trigger: Calling `broadcast`/`broadcast_in` outside of a rayon worker thread such that the stealing CountLatch has no `owner` context — e.g. invoking broadcast-based APIs from a non-worker thread where the code path expects an owned worker.

Common situations: Calling `ThreadPool::broadcast` from a thread other than expected context, or mixing scopes/broadcast across manually managed threads.

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 rayon-rs/rayon@ee0a00bdb1 (2026-09-07). Data as JSON: /api/errors/5ece821930f3899e. Report an issue: GitHub.

Appendix: source

Thrown at rayon-core/src/latch.rs:397

                },
            },
        }
    }

    #[inline]
    pub(super) fn increment(&self) {
        let old_counter = self.counter.fetch_add(1, Ordering::Relaxed);
        debug_assert!(old_counter != 0);
    }

    pub(super) fn wait(&self, owner: Option<&WorkerThread>) {
        match &self.kind {
            CountLatchKind::Stealing {
                latch,
                registry,
                worker_index,
            } => unsafe {
                let owner = owner.expect("owner thread");
                debug_assert_eq!(registry.id(), owner.registry().id());
                debug_assert_eq!(*worker_index, owner.index());
                owner.wait_until(latch);
            },
            CountLatchKind::Blocking { latch } => latch.wait(),
        }
    }
}

impl Latch for CountLatch {
    #[inline]
    unsafe fn set(this: *const Self) {
        unsafe {
            if (*this).counter.fetch_sub(1, Ordering::SeqCst) == 1 {
                // NOTE: Once we call `set` on the internal `latch`,
                // the target may proceed and invalidate `this`!
                match (*this).kind {
                    CountLatchKind::Stealing {

View on GitHub (pinned to ee0a00bdb1)