{"record":{"id":"879471aa64a9e1a6","repo":"PyO3/pyo3","slug":"out-of-range-integral-type-conversion-attempted-on-879471","errorCode":null,"errorMessage":"out of range integral type conversion attempted on `elements.len()`","messagePattern":"out of range integral type conversion attempted on `elements\\.len\\(\\)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/types/tuple.rs","lineNumber":44,"sourceCode":"use core::iter::FusedIterator;\n#[cfg(feature = \"nightly\")]\nuse core::num::NonZero;\n\n#[cfg(all(not(any(PyPy, GraalPy)), any(not(Py_LIMITED_API), Py_3_12)))]\nuse libc::size_t;\n\n#[inline]\n#[track_caller]\n#[cfg_attr(RustPython, allow(unused_mut))]\nfn try_new_from_iter<'py>(\n    py: Python<'py>,\n    mut elements: impl ExactSizeIterator<Item = PyResult<Bound<'py, PyAny>>>,\n) -> PyResult<Bound<'py, PyTuple>> {\n    // PyTuple_New checks for overflow but has a bad error message, so we check ourselves\n    let len: Py_ssize_t = elements\n        .len()\n        .try_into()\n        .expect(\"out of range integral type conversion attempted on `elements.len()`\");\n\n    #[cfg(not(RustPython))]\n    let (tup, counter) = unsafe {\n        let ptr = ffi::PyTuple_New(len);\n\n        // - Panics if the ptr is null\n        // - Cleans up the tuple if `convert` or the asserts panic\n        let tup = ptr.assume_owned(py).cast_into_unchecked();\n\n        let mut counter: Py_ssize_t = 0;\n\n        for obj in (&mut elements).take(len as usize) {\n            #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n            ffi::PyTuple_SET_ITEM(ptr, counter, obj?.into_ptr());\n            #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))]\n            ffi::PyTuple_SetItem(ptr, counter, obj?.into_ptr());\n            counter += 1;\n        }","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/PyO3/pyo3/blob/ac9b6899d348be4d54614d060dea53a645a12e36/src/types/tuple.rs#L26-L62","documentation":"`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.","triggerScenarios":"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.","commonSituations":"wasm32/i686 builds handling huge generated collections; bespoke iterators returning bogus lengths from `size_hint`/`len`.","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"],"exampleFix":"// before\nlet tup = PyTuple::new(py, huge_iter)?;\n// after\nlet items: Vec<_> = huge_iter.take(1_000_000).collect();\nlet tup = PyTuple::new(py, items)?;","handlingStrategy":"validation","validationCode":"fn tuple_len_safe<T>(items: impl ExactSizeIterator<Item = T>) -> bool {\n    items.len() <= isize::MAX as usize\n}","typeGuard":null,"tryCatchPattern":"let result = std::panic::catch_unwind(|| PyTuple::new(py, items.clone()));","preventionTips":["Cap input iterator lengths on 32-bit/wasm targets","Fix any custom ExactSizeIterator that lies about len()","Build tuples incrementally for unbounded input"],"tags":["pyo3","panic","overflow","tuple"],"backgroundTag":"ssize-overflow-panic","analyzedSha":"ac9b6899d348be4d54614d060dea53a645a12e36","analyzedAt":"2026-09-05T09:20:35.319Z","contentChangedAt":"2026-09-05T09:20:35.319Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}