pola-rs/polars · error · PyPolarsErr

{0}

Error message

{0}

What it means

PyPolarsErr::Other is the escape hatch in pyo3-polars for arbitrary error strings: it wraps a plain String and its Display (used as the Python error message) is just the inner text. Any Rust code raising PyPolarsErr::Other(msg) surfaces msg verbatim to Python.

Solutions

  1. Read the message text directly — it is the raw Rust-side error string; locate the call site raising Other with that text.
  2. In Rust, prefer mapping to specific PolarsError variants or thiserror enums instead of Other for actionable errors.
  3. Include context (parameter names, values) in the format! when raising Other so the Python message is actionable.

Example fix

// before
PyPolarsErr::Other(format!("bad value"))
// after
PyPolarsErr::Other(format!("bad value for column '{}': got {:?}", name, value))
Defensive patterns

Strategy: try-catch

Validate before calling

# Python: validate inputs before they reach the Rust boundary
if not isinstance(value, (str, int, float)):
    raise TypeError(f"unsupported value type for rust interop: {type(value)}")

Try / catch

try:
    result = rust_backed_call(args)
except Exception as e:  # PyPolarsErr::Other surfaces as generic error
    raise RuntimeError(f"pyo3-polars op failed: {e}") from e

Prevention

When it happens

Trigger: Rust-side polars/interop code calls PyPolarsErr::Other(format!(...)) for errors that do not map to a PolarsError variant, so the Python exception message equals whatever string was formatted at the call site.

Common situations: Seeing an opaque one-line message from pyo3-polars-backed operations (e.g. custom Rust plugins, value conversion failures) with no structured error type behind it; debugging plugins that use Other for all errors.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/fccda95c87afaa1d. Report an issue: GitHub.

Appendix: source

Thrown at pyo3-polars/pyo3-polars/src/error.rs:15

use std::fmt::{Debug, Formatter};

use polars::prelude::PolarsError;
use pyo3::create_exception;
use pyo3::exceptions::{
    PyAssertionError, PyException, PyIOError, PyIndexError, PyRuntimeError, PyValueError,
};
use pyo3::prelude::*;
use thiserror::Error;

#[derive(Error)]
pub enum PyPolarsErr {
    #[error(transparent)]
    Polars(#[from] PolarsError),
    #[error("{0}")]
    Other(String),
}

impl std::convert::From<PyPolarsErr> for PyErr {
    fn from(err: PyPolarsErr) -> PyErr {
        fn convert(err: PolarsError) -> PyErr {
            match err {
                PolarsError::AssertionError(error) => PyAssertionError::new_err(error.to_string()),
                PolarsError::ComputeError(err) => ComputeError::new_err(err.to_string()),
                PolarsError::NoData(err) => NoDataError::new_err(err.to_string()),
                PolarsError::ShapeMismatch(err) => ShapeError::new_err(err.to_string()),
                PolarsError::SchemaMismatch(err) => SchemaError::new_err(err.to_string()),
                PolarsError::IO { error, .. } => PyIOError::new_err(error.to_string()),
                PolarsError::OutOfBounds(err) => PyIndexError::new_err(err.to_string()),
                PolarsError::InvalidOperation(err) => PyValueError::new_err(err.to_string()),
                PolarsError::Duplicate(err) => DuplicateError::new_err(err.to_string()),
                PolarsError::ColumnNotFound(err) => ColumnNotFound::new_err(err.to_string()),
                PolarsError::SchemaFieldNotFound(err) => {

View on GitHub (pinned to fe841f959e)