PyO3/pyo3 · error
expected error
Error message
expected error
What it means
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.
Source
Thrown at src/types/string.rs:275
/// This function is similar to [`format!`], but it returns a Python string object instead of a Rust string.
#[inline]
pub fn from_fmt<'py>(
py: Python<'py>,
args: fmt::Arguments<'_>,
) -> PyResult<Bound<'py, PyString>> {
if let Some(static_string) = args.as_str() {
return Ok(PyString::new(py, static_string));
};
#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]
{
use crate::fmt::PyUnicodeWriter;
use core::fmt::Write as _;
let mut writer = PyUnicodeWriter::new(py)?;
writer
.write_fmt(args)
.map_err(|_| writer.take_error().expect("expected error"))?;
writer.into_py_string()
}
#[cfg(any(not(Py_3_14), Py_LIMITED_API))]
{
Ok(PyString::new(py, &format!("{args}")))
}
}
}
/// Implementation of functionality for [`PyString`].
///
/// These methods are defined for the `Bound<'py, PyString>` smart pointer, so to use method call
/// syntax these methods are separated into a trait, because stable Rust does not yet support
/// `arbitrary_self_types`.
#[doc(alias = "PyString")]
pub trait PyStringMethods<'py>: crate::sealed::Sealed {
/// Gets the Python string as a Rust UTF-8 string slice.View on GitHub (pinned to ac9b6899d3)
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!`
Example fix
// before
let s = PyString::from_fmt(py, format_args!("{}", custom))?;
// after
let s = PyString::new(py, &format!("{}", custom)); Defensive patterns
Strategy: fallback
Validate before calling
// ensure Display impls cannot fail; test them
let text = format!("{}", value); // panics-safe pre-check in Rust Try / catch
// catch the panic and fall back to PyString::new
let s = std::panic::catch_unwind(|| PyString::from_fmt(py, args).unwrap())
.unwrap_or_else(|_| PyString::new(py, &format!("{}", args_display))); Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Attaching a thread to the interpreter is prohibited while a
- Cannot attach to the Python interpreter while it is finalizi
- Attaching a thread to the interpreter is currently prohibite
- {}
- Unknown return value from PyDict_SetDefaultRef: {x}
AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05).
Data as JSON: /api/errors/e0e98a844adffb71.
Report an issue: GitHub.