PyO3/pyo3 · warning

failed to create Python string

Error message

failed to create Python string

What it means

`CastError` formatting in pyo3 converts the human-readable description of a failed `isinstance`-style check (from/classinfo pair) into a Python string via `into_py_any`. The `.expect("failed to create Python string")` panics if that conversion to a Python `str` object fails. This is a nested failure: the primary failure is the type cast, and this panic only occurs if even building the error message fails.

Source

Thrown at src/err/cast_error.rs:79

    }
}

struct CastErrorArguments {
    from: Py<PyAny>,
    classinfo: Py<PyAny>,
}

impl PyErrArguments for CastErrorArguments {
    fn arguments(self, py: Python<'_>) -> Py<PyAny> {
        format!(
            "{}",
            DisplayCastError {
                from: &self.from.into_bound(py),
                classinfo: &self.classinfo.into_bound(py),
            }
        )
        .into_py_any(py)
        .expect("failed to create Python string")
    }
}

/// Convert `CastError` to Python `TypeError`.
impl core::convert::From<CastError<'_, '_>> for PyErr {
    fn from(err: CastError<'_, '_>) -> PyErr {
        let args = CastErrorArguments {
            from: err.from.to_owned().unbind(),
            classinfo: err.classinfo.unbind(),
        };

        exceptions::PyTypeError::new_err(args)
    }
}

impl core::error::Error for CastError<'_, '_> {}

impl core::fmt::Display for CastError<'_, '_> {

View on GitHub (pinned to ac9b6899d3)

Solutions

  1. Fix the underlying argument-type mismatch so the CastError is never constructed
  2. Avoid calling extension APIs after `Py_Finalize` / during interpreter shutdown
  3. Check memory availability if the process is near OOM
  4. Upgrade pyo3; error formatting paths have changed across versions

Example fix

// before
obj.extract::<MyType>()  # passing wrong Python type at shutdown
// after
# pass the correct type while the interpreter is fully alive
func(MyType(...))
Defensive patterns

Strategy: validation

Validate before calling

# Validate argument types before calling the Rust extension
isinstance(value, expected_type) or raise TypeError(f'expected {expected_type}, got {type(value)}')

Type guard

def is_expected_type(value, expected: type) -> bool:
    return isinstance(value, expected)

Prevention

When it happens

Trigger: `DowncastError`/`CastError` Display formatting being converted with `.into_py_any(py)` when the Python interpreter cannot allocate a string, e.g. during interpreter finalization or out-of-memory.

Common situations: Calling Rust extension functions with wrong argument types during interpreter shutdown; extremely memory-constrained environments; panics surfacing as 'failed to create Python string' instead of a clean TypeError.

Related errors


AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05). Data as JSON: /api/errors/3d10adaf0dcaca02. Report an issue: GitHub.