rayon-rs/rayon · error

unzip consumers didn't execute!

Error message

unzip consumers didn't execute!

What it means

`UnzipConsumer::drive_unindexed` returns the left consumer's result via `Option::expect`; it panics if the right side's `par_extend` never drove the iterator, leaving no result for the left. This indicates the unzip consumer protocol was violated internally.

Solutions

  1. Upgrade rayon to the latest version
  2. If using a custom Consumer/UnindexedConsumer impl, ensure it drives all fed items in `par_extend`
  3. Work around by splitting the iterator: `let (a, b): (Vec<_>, Vec<_>) = iter.map(|x| (f(x), g(x))).unzip();` with collected intermediates
  4. File a minimal repro on the rayon issue tracker

Example fix

// before
custom_unzip_consumer_drive(iter); // protocol-violating consumer
// after
let (left, right): (Vec<_>, Vec<_>) = iter.unzip();
Defensive patterns

Strategy: try-catch

Try / catch

let r = catch_unwind(AssertUnwindSafe(|| iter.unzip()));
if r.is_err() { /* fall back to sequential unzip */ }

Prevention

When it happens

Trigger: Unzipping an unindexed parallel iterator where the right consumer's `par_extend` fails to actually consume the items (internal consumer contract violation), so `result` remains None.

Common situations: Rare; arises from rayon bugs or custom `Consumer` implementations used with `unzip` that don't drive the fed iterator.

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/af01478e9aa1fe0d. Report an issue: GitHub.

Appendix: source

Thrown at src/iter/unzip.rs:225

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
    where
        C: UnindexedConsumer<Self::Item>,
    {
        let mut result = None;
        {
            // Now it's time to find the consumer for type `B`
            let iter = UnzipB {
                base: self.base,
                op: self.op,
                left_consumer: consumer,
                left_result: &mut result,
            };
            self.b.par_extend(iter);
        }
        // NB: If for some reason `b.par_extend` doesn't actually drive the
        // iterator, then we won't have a result for the left side to return
        // at all.  We can't fake an arbitrary consumer's result, so panic.
        result.expect("unzip consumers didn't execute!")
    }

    fn opt_len(&self) -> Option<usize> {
        if OP::indexable() {
            self.base.opt_len()
        } else {
            None
        }
    }
}

/// A fake iterator to intercept the `Consumer` for type `B`.
struct UnzipB<'r, I, OP, CA>
where
    I: ParallelIterator,
    OP: UnzipOp<I::Item>,
    CA: UnindexedConsumer<OP::Left>,
{

View on GitHub (pinned to ee0a00bdb1)