{"record":{"id":"57f05f9d614b15e1","repo":"PyO3/pyo3","slug":"failed-to-convert-tuple-to-list","errorCode":null,"errorMessage":"failed to convert tuple to list","messagePattern":"failed to convert tuple to list","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/types/tuple.rs","lineNumber":340,"sourceCode":"    fn index<V>(&self, value: V) -> PyResult<usize>\n    where\n        V: IntoPyObject<'py>,\n    {\n        self.as_sequence().index(value)\n    }\n\n    fn iter(&self) -> BoundTupleIterator<'py> {\n        BoundTupleIterator::new(self.clone())\n    }\n\n    fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py> {\n        self.as_borrowed().iter_borrowed()\n    }\n\n    fn to_list(&self) -> Bound<'py, PyList> {\n        self.as_sequence()\n            .to_list()\n            .expect(\"failed to convert tuple to list\")\n    }\n}\n\nimpl<'a, 'py> Borrowed<'a, 'py, PyTuple> {\n    fn get_borrowed_item(self, index: usize) -> PyResult<Borrowed<'a, 'py, PyAny>> {\n        unsafe {\n            ffi::PyTuple_GetItem(self.as_ptr(), index as Py_ssize_t)\n                .assume_borrowed_or_err(self.py())\n        }\n    }\n\n    /// # Safety\n    ///\n    /// See `get_item_unchecked` in `PyTupleMethods`.\n    unsafe fn get_borrowed_item_unchecked(self, index: usize) -> Borrowed<'a, 'py, PyAny> {\n        cfg_select! {\n            // SAFETY: caller has upheld the safety contract\n            not(any(Py_LIMITED_API, PyPy, GraalPy)) => unsafe {","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/PyO3/pyo3/blob/ac9b6899d348be4d54614d060dea53a645a12e36/src/types/tuple.rs#L322-L358","documentation":"`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.","triggerScenarios":"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.","commonSituations":"Alternate interpreters (RustPython/GraalPy/PyPy) with incomplete sequence APIs, or embedding code that corrupted the tuple object.","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"],"exampleFix":"// before\nlet list = tuple.to_list();\n// after\nlet list = PyList::new(py, tuple.iter().map(|o| o.clone().unbind()))?;","handlingStrategy":"try-catch","validationCode":"// ensure the object is a real tuple before conversion\nif not isinstance(t, tuple):\n    raise TypeError(\"expected tuple\")","typeGuard":"fn is_tuple(obj: &Bound<'_, PyAny>) -> bool {\n    obj.downcast::<PyTuple>().is_ok()\n}","tryCatchPattern":"// fallible conversion instead of the panicking to_list\nlet list = PyList::new(py, tup.iter().map(|o| o.clone().unbind()))?;","preventionTips":["Construct tuples only via checked pyo3 APIs","Avoid unsafe refcount manipulation that can corrupt objects","Test conversions on the target interpreter"],"tags":["pyo3","panic","tuple","list"],"backgroundTag":"tuple-to-list-conversion-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"}