{"record":{"id":"13ab263b970c6f65","repo":"PyO3/pyo3","slug":"attempted-to-fetch-exception-but-none-was-set","errorCode":null,"errorMessage":"attempted to fetch exception but none was set","messagePattern":"attempted to fetch exception but none was set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/err/mod.rs","lineNumber":664,"sourceCode":"    #[inline]\n    fn from_state(state: PyErrState) -> PyErr {\n        PyErr { state }\n    }\n\n    #[inline]\n    fn normalized(&self, py: Python<'_>) -> &PyErrStateNormalized {\n        self.state.as_normalized(py)\n    }\n}\n\n/// Called when `PyErr::fetch` is called but no exception is set.\n#[cold]\n#[cfg_attr(debug_assertions, track_caller)]\nfn failed_to_fetch() -> PyErr {\n    const FAILED_TO_FETCH: &str = \"attempted to fetch exception but none was set\";\n\n    if cfg!(debug_assertions) {\n        panic!(\"{}\", FAILED_TO_FETCH)\n    } else {\n        crate::exceptions::PySystemError::new_err(FAILED_TO_FETCH)\n    }\n}\n\nimpl core::fmt::Debug for PyErr {\n    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {\n        Python::attach(|py| {\n            f.debug_struct(\"PyErr\")\n                .field(\"type\", &self.get_type(py))\n                .field(\"value\", self.value(py))\n                .field(\n                    \"traceback\",\n                    &self.traceback(py).map(|tb| match tb.format() {\n                        Ok(s) => s,\n                        Err(err) => {\n                            err.write_unraisable(py, Some(&tb));\n                            // It would be nice to format what we can of the","sourceCodeStart":646,"sourceCodeEnd":682,"githubUrl":"https://github.com/PyO3/pyo3/blob/ac9b6899d348be4d54614d060dea53a645a12e36/src/err/mod.rs#L646-L682","documentation":"failed_to_fetch is the fallback when pyo3 must produce a PyErr but Python's error indicator holds nothing (PyErr::take found no exception). In debug builds it panics; in release it returns a PySystemError carrying the same message.","triggerScenarios":"Calling an FFI function that should have set a Python exception (returned NULL/-1) but did not; calling PyErr::take or building PyErr from a null result when the GIL was acquired with no error set; misuse of unsafe APIs that assume an error indicator.","commonSituations":"Buggy C extension or libc call returning failure without setting an exception; race where another thread cleared the error indicator; pyo3 internal invariant violation during interpreter shutdown.","solutions":["Find the underlying FFI call that signaled failure without setting the exception and fix it (call PyErr_SetFromErrno or similar on failure)","Reproduce in debug mode: the panic gives a precise backtrace to the offending call site","Check for concurrent error-indicator clearing (other threads calling PyErr::clear/fetch) around the failing call"],"exampleFix":"// before: assumes any NULL return means an exception is set\nlet obj = NonNull::new(ffi_call()).ok()?; // then PyErr::take\n// after: set an exception if none exists\nlet ptr = ffi_call();\nif ptr.is_null() {\n    if PyErr::take(py).is_none() {\n        PyErr::new::<PySystemError, _>(\"call failed without exception\").into();\n    }\n    return Err(...);\n}","handlingStrategy":"try-catch","validationCode":"// after a failing FFI call, ensure an exception exists before fetching\nif PyErr::take(py).is_none() {\n    PyErr::new::<pyo3::exceptions::PySystemError, _>(\"ffi call failed without setting an exception\");\n}","typeGuard":"fn error_indicator_set(py: Python<'_>) -> bool { PyErr::take(py).is_some() }","tryCatchPattern":"// run in debug builds so failed_to_fetch panics with a precise backtrace\n#[cfg(debug_assertions)]\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| unsafe { ffi_call() }));","preventionTips":["Check every FFI return value and set a Python exception on failure yourself","Avoid PyErr::take/fetch assumptions from non-Python threads","Reproduce with debug_assertions enabled to get exact call sites"],"tags":["pyerr","ffi","error-indicator","panic"],"backgroundTag":"missing-python-exception-state","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"}