PyO3/pyo3 · error
out of range integral type conversion attempted on `elements
Error message
out of range integral type conversion attempted on `elements.len()`
What it means
`PyTuple::new` (via `try_new_from_iter`) converts the input iterator's `ExactSizeIterator::len()` into C's `Py_ssize_t`; if the length exceeds `Py_ssize_t::MAX` the `try_into()` fails and this expect panics. PyO3 checks this itself because `PyTuple_New`'s overflow error is unhelpful.
Source
Thrown at src/types/tuple.rs:44
use core::iter::FusedIterator;
#[cfg(feature = "nightly")]
use core::num::NonZero;
#[cfg(all(not(any(PyPy, GraalPy)), any(not(Py_LIMITED_API), Py_3_12)))]
use libc::size_t;
#[inline]
#[track_caller]
#[cfg_attr(RustPython, allow(unused_mut))]
fn try_new_from_iter<'py>(
py: Python<'py>,
mut elements: impl ExactSizeIterator<Item = PyResult<Bound<'py, PyAny>>>,
) -> PyResult<Bound<'py, PyTuple>> {
// PyTuple_New checks for overflow but has a bad error message, so we check ourselves
let len: Py_ssize_t = elements
.len()
.try_into()
.expect("out of range integral type conversion attempted on `elements.len()`");
#[cfg(not(RustPython))]
let (tup, counter) = unsafe {
let ptr = ffi::PyTuple_New(len);
// - Panics if the ptr is null
// - Cleans up the tuple if `convert` or the asserts panic
let tup = ptr.assume_owned(py).cast_into_unchecked();
let mut counter: Py_ssize_t = 0;
for obj in (&mut elements).take(len as usize) {
#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
ffi::PyTuple_SET_ITEM(ptr, counter, obj?.into_ptr());
#[cfg(any(Py_LIMITED_API, PyPy, GraalPy))]
ffi::PyTuple_SetItem(ptr, counter, obj?.into_ptr());
counter += 1;
}View on GitHub (pinned to ac9b6899d3)
Solutions
- Chunk or reduce the collection before building the tuple
- Fix the custom iterator's `len()`/`size_hint` implementation
- Build incrementally with a `PyTupleBuilder`-style approach or return a `PyResult` error instead
Example fix
// before let tup = PyTuple::new(py, huge_iter)?; // after let items: Vec<_> = huge_iter.take(1_000_000).collect(); let tup = PyTuple::new(py, items)?;
Defensive patterns
Strategy: validation
Validate before calling
fn tuple_len_safe<T>(items: impl ExactSizeIterator<Item = T>) -> bool {
items.len() <= isize::MAX as usize
} Try / catch
let result = std::panic::catch_unwind(|| PyTuple::new(py, items.clone()));
Prevention
- Cap input iterator lengths on 32-bit/wasm targets
- Fix any custom ExactSizeIterator that lies about len()
- Build tuples incrementally for unbounded input
When it happens
Trigger: Calling `PyTuple::new(py, iterable)` where the iterator's `len()` exceeds `Py_ssize_t::MAX` — an enormous collection on 32-bit targets, or a custom `ExactSizeIterator` whose `len()` lies.
Common situations: wasm32/i686 builds handling huge generated collections; bespoke iterators returning bogus lengths from `size_hint`/`len`.
Related errors
- out of range integral type conversion attempted on `elements
- failed to convert tuple to list
- 0 < N <= 12
- 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/879471aa64a9e1a6.
Report an issue: GitHub.