PyO3/pyo3 · error

Converting PyErr arguments failed: {}

Error message

Converting PyErr arguments failed: {}

What it means

PyErr::arguments converts the exception's arguments into a Python object and is documented as infallible, but IntoPyObject can now fail. Since the signature can't return the error, pyo3 panics with the conversion error.

Source

Thrown at src/err/mod.rs:69

/// Represents the result of a Python call.
pub type PyResult<T> = Result<T, PyErr>;

/// Helper conversion trait that allows to use custom arguments for lazy exception construction.
pub trait PyErrArguments: Send + Sync {
    /// Arguments for exception
    fn arguments(self, py: Python<'_>) -> Py<PyAny>;
}

impl<T> PyErrArguments for T
where
    T: for<'py> IntoPyObject<'py> + Send + Sync,
{
    fn arguments(self, py: Python<'_>) -> Py<PyAny> {
        // FIXME: `arguments` should become fallible
        match self.into_pyobject(py) {
            Ok(obj) => obj.into_any().unbind(),
            Err(e) => panic!("Converting PyErr arguments failed: {}", e.into()),
        }
    }
}

impl PyErr {
    /// Creates a new PyErr of type `T`.
    ///
    /// `args` can be:
    /// * a tuple: the exception instance will be created using the equivalent to the Python
    ///   expression `T(*tuple)`
    /// * any other value: the exception instance will be created using the equivalent to the Python
    ///   expression `T(value)`
    ///
    /// This exception instance will be initialized lazily. This avoids the need for the Python GIL
    /// to be held, but requires `args` to be `Send` and `Sync`. If `args` is not `Send` or `Sync`,
    /// consider using [`PyErr::from_value`] instead.
    ///
    /// If `T` does not inherit from `BaseException`, then a `TypeError` will be returned.

View on GitHub (pinned to ac9b6899d3)

Solutions

  1. Ensure the value passed to new_err has an infallible IntoPyObject impl (or convert to a supported type first, e.g. String)
  2. Provide your own error message instead of relying on arguments conversion
  3. Downcast/manually build the exception with .into_pyobject and handle the Err case yourself

Example fix

// before
PyValueError::new_err(my_custom_obj)
// after
PyValueError::new_err(format!("{}", my_custom_obj))
Defensive patterns

Strategy: validation

Validate before calling

fn args_are_trivially_convertible<T: for<'py> IntoPyObject<'py>>() -> bool { true } // prefer plain str/String/numbers as PyErr args

Prevention

When it happens

Trigger: Creating an exception whose args' IntoPyObject conversion fails (e.g. PyTypeError::new_err(value) where value's IntoPyObject impl returns Err, such as a type that can't be converted in the current interpreter configuration).

Common situations: new_err with a custom type whose IntoPyObject conversion errors at runtime; API evolution where arguments() was fallible-ized but callers kept the old infallible path.

Related errors


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