PyO3/pyo3 · error
frozenset iteration should be infallible
Error message
frozenset iteration should be infallible
What it means
PyO3 wraps Python's frozenset iterator and asserts that each step of iteration cannot fail, since iterating a frozenset over which the interpreter holds a borrowed reference is guaranteed to yield items without error. The Rust `next()` unwraps the inner PyResult with `.expect()`, so if the underlying C-API iteration ever returns an error this panic fires, indicating an interpreter invariant violation rather than user error.
Source
Thrown at src/types/frozenset.rs:238
}
/// PyO3 implementation of an iterator for a Python `frozenset` object.
pub struct BoundFrozenSetIterator<'py>(Bound<'py, PyIterator>);
impl<'py> BoundFrozenSetIterator<'py> {
pub(super) fn new(set: Bound<'py, PyFrozenSet>) -> Self {
Self(PyIterator::from_object(&set).expect("frozenset should always be iterable"))
}
}
impl<'py> Iterator for BoundFrozenSetIterator<'py> {
type Item = Bound<'py, super::PyAny>;
/// Advances the iterator and returns the next value.
fn next(&mut self) -> Option<Self::Item> {
self.0
.next()
.map(|result| result.expect("frozenset iteration should be infallible"))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = ExactSizeIterator::len(self);
(len, Some(len))
}
#[inline]
fn count(self) -> usize
where
Self: Sized,
{
self.len()
}
}
impl ExactSizeIterator for BoundFrozenSetIterator<'_> {
fn len(&self) -> usize {View on GitHub (pinned to ac9b6899d3)
Solutions
- Audit code for unsafe manipulation or premature deallocation of the frozenset/iterator while iterating
- Verify the Python interpreter build/embedding setup is standard CPython and refcounts are not corrupted
- Report to pyo3 if reproducible on a supported interpreter, with a minimal reproducer
Example fix
// before: panic propagates out of iterator
for item in frozenset.iter() { ... }
// after: iterate defensively over a plain Python iteration and handle errors
let it = frozenset.as_any().call_method0("__iter__")?;
while let Some(item) = it.call_method0("__next__").transpose()? { /* use item */ } Defensive patterns
Strategy: try-catch
Validate before calling
// Python-side sanity check before Rust iteration
if not isinstance(fs, frozenset):
raise TypeError("expected frozenset") Type guard
fn is_frozenset(obj: &Bound<'_, PyAny>) -> bool {
obj.downcast::<PyFrozenSet>().is_ok()
} Try / catch
// use fallible iteration instead of the panicking wrapper
let it = obj.call_method0("__iter__")?;
loop {
match it.call_method0("__next__") {
Ok(item) => { /* use item */ }
Err(e) if e.is_instance_of::<PyStopIteration>(py) => break,
Err(e) => return Err(e),
}
} Prevention
- Use checked downcasts (downcast/extract) before iterating
- Never mutate or free collections from callbacks while Rust iterates them
- Test on the actual target interpreter (CPython vs RustPython/GraalPy)
When it happens
Trigger: Calling `.next()` on a `BoundSetIterator`/frozenset iterator (e.g. via `frozenset.iter()` in Rust or any `for` loop over a `&PyFrozenSet`) when the underlying CPython iterator returns an error — practically only when the CPython interpreter state is corrupt, the object was mutated/freed improperly, or an FFI misuse broke the iterator.
Common situations: Unsafe FFI code invalidating the frozenset or its iterator, embedding CPython in a host app where object refcounts were mishandled, or running against a non-CPython interpreter (RustPython/GraalPy) whose iterator error behavior diverges from CPython's.
Related errors
- frozenset should always be iterable
- set should always be iterable
- set iteration should be infallible
- Attaching a thread to the interpreter is prohibited while a
- Cannot attach to the Python interpreter while it is finalizi
AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05).
Data as JSON: /api/errors/9aa8c5b660ffb901.
Report an issue: GitHub.