PyO3/pyo3 · error
failed to convert tuple to list
Error message
failed to convert tuple to list
What it means
`ToPyObject for PyTuple`'s `to_list` converts the tuple to a Python list via its sequence protocol and asserts success, since any tuple must be convertible to a list. The panic fires if `PySequence::to_list` returns `Err`, meaning the CPython sequence conversion failed — an interpreter invariant violation, not expected user error.
Source
Thrown at src/types/tuple.rs:340
fn index<V>(&self, value: V) -> PyResult<usize>
where
V: IntoPyObject<'py>,
{
self.as_sequence().index(value)
}
fn iter(&self) -> BoundTupleIterator<'py> {
BoundTupleIterator::new(self.clone())
}
fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py> {
self.as_borrowed().iter_borrowed()
}
fn to_list(&self) -> Bound<'py, PyList> {
self.as_sequence()
.to_list()
.expect("failed to convert tuple to list")
}
}
impl<'a, 'py> Borrowed<'a, 'py, PyTuple> {
fn get_borrowed_item(self, index: usize) -> PyResult<Borrowed<'a, 'py, PyAny>> {
unsafe {
ffi::PyTuple_GetItem(self.as_ptr(), index as Py_ssize_t)
.assume_borrowed_or_err(self.py())
}
}
/// # Safety
///
/// See `get_item_unchecked` in `PyTupleMethods`.
unsafe fn get_borrowed_item_unchecked(self, index: usize) -> Borrowed<'a, 'py, PyAny> {
cfg_select! {
// SAFETY: caller has upheld the safety contract
not(any(Py_LIMITED_API, PyPy, GraalPy)) => unsafe {View on GitHub (pinned to ac9b6899d3)
Solutions
- Replace direct `to_list` with `PyList::new(py, tuple.iter())` and handle errors via `?`
- Verify interpreter support/version for the sequence conversion API
- Report a reproducer to pyo3 if it occurs on stock CPython
Example fix
// before let list = tuple.to_list(); // after let list = PyList::new(py, tuple.iter().map(|o| o.clone().unbind()))?;
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the object is a real tuple before conversion
if not isinstance(t, tuple):
raise TypeError("expected tuple") Type guard
fn is_tuple(obj: &Bound<'_, PyAny>) -> bool {
obj.downcast::<PyTuple>().is_ok()
} Try / catch
// fallible conversion instead of the panicking to_list let list = PyList::new(py, tup.iter().map(|o| o.clone().unbind()))?;
Prevention
- Construct tuples only via checked pyo3 APIs
- Avoid unsafe refcount manipulation that can corrupt objects
- Test conversions on the target interpreter
When it happens
Trigger: Calling `to_list` on a `Bound<PyTuple>` (including via `tuple.to_object`/conversion paths) when `PySequence_List`-style conversion errors — practically only with corrupted tuple objects or a non-CPython interpreter whose sequence protocol diverges.
Common situations: Alternate interpreters (RustPython/GraalPy/PyPy) with incomplete sequence APIs, or embedding code that corrupted the tuple object.
Related errors
- out of range integral type conversion attempted on `elements
- out of range integral type conversion attempted on `elements
- 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/57f05f9d614b15e1.
Report an issue: GitHub.