{"record":{"id":"e0e98a844adffb71","repo":"PyO3/pyo3","slug":"expected-error","errorCode":null,"errorMessage":"expected error","messagePattern":"expected error","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/types/string.rs","lineNumber":275,"sourceCode":"    /// This function is similar to [`format!`], but it returns a Python string object instead of a Rust string.\n    #[inline]\n    pub fn from_fmt<'py>(\n        py: Python<'py>,\n        args: fmt::Arguments<'_>,\n    ) -> PyResult<Bound<'py, PyString>> {\n        if let Some(static_string) = args.as_str() {\n            return Ok(PyString::new(py, static_string));\n        };\n\n        #[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n        {\n            use crate::fmt::PyUnicodeWriter;\n            use core::fmt::Write as _;\n\n            let mut writer = PyUnicodeWriter::new(py)?;\n            writer\n                .write_fmt(args)\n                .map_err(|_| writer.take_error().expect(\"expected error\"))?;\n            writer.into_py_string()\n        }\n\n        #[cfg(any(not(Py_3_14), Py_LIMITED_API))]\n        {\n            Ok(PyString::new(py, &format!(\"{args}\")))\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyString`].\n///\n/// These methods are defined for the `Bound<'py, PyString>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyString\")]\npub trait PyStringMethods<'py>: crate::sealed::Sealed {\n    /// Gets the Python string as a Rust UTF-8 string slice.","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/PyO3/pyo3/blob/ac9b6899d348be4d54614d060dea53a645a12e36/src/types/string.rs#L257-L293","documentation":"On CPython 3.14+ (or with the full API), `PyString::from_fmt` formats directly into a `PyUnicodeWriter`. `write_fmt` swallows the real error into the writer, and the code then asserts `take_error()` returns `Some` — if it returns `None` while `write_fmt` failed, the `.expect(\"expected error\")` panics because the writer's internal error state is missing.","triggerScenarios":"Calling `PyString::from_fmt(py, args)` where the `format_args!` `Write` implementation fails (e.g. a custom `Display` impl returns an error, or formatting raises into the writer) but the writer does not record an error internally — an internal inconsistency, typically triggered by a `Display` impl that returns `fmt::Error` without the writer capturing a Python error.","commonSituations":"User `Display` implementations returning `Err(fmt::Error)` manually, panicking/unwinding inside `Display`, or a pyo3 bug where `write_fmt` fails for a non-error reason.","solutions":["Ensure your types' `Display` impls never return `Err` manually and never panic","Pre-format to a Rust `String` and use `PyString::new` as a fallback","Report a reproducer to pyo3 if it occurs with a plain `format_args!`"],"exampleFix":"// before\nlet s = PyString::from_fmt(py, format_args!(\"{}\", custom))?;\n// after\nlet s = PyString::new(py, &format!(\"{}\", custom));","handlingStrategy":"fallback","validationCode":"// ensure Display impls cannot fail; test them\nlet text = format!(\"{}\", value); // panics-safe pre-check in Rust","typeGuard":null,"tryCatchPattern":"// catch the panic and fall back to PyString::new\nlet s = std::panic::catch_unwind(|| PyString::from_fmt(py, args).unwrap())\n    .unwrap_or_else(|_| PyString::new(py, &format!(\"{}\", args_display)));","preventionTips":["Never return Err(fmt::Error) manually from Display impls","Keep Display impls panic-free and allocation-light","Use PyString::new with format!() when formatting can fail"],"tags":["pyo3","panic","string","formatting"],"backgroundTag":"unicode-writer-state-loss","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"}