pola-rs/polars · error

pyarrow is required for converting a pandas dataframe to Pol

Error message

pyarrow is required for converting a pandas dataframe to Polars, unless each of its columns is a simple numpy-backed one (e.g. 'int64', 'bool', 'float32' - not 'Int64')

What it means

Converting a pandas DataFrame to Polars goes through pyarrow unless every column is a simple numpy-backed dtype that polars can read directly (int64, bool, float32, ...). Nullable/extension dtypes ('Int64', 'boolean'), 'category', timezone-aware datetimes, and object columns require the arrow path — so when pyarrow is not installed, this ImportError is raised, explicitly noting the numpy-only exception.

Source

Thrown at py-polars/src/polars/_utils/construction/dataframe.py:1120

            return PyDataFrame.empty_with_height(data.shape[0])

        if all(is_simple_numpy_backed_pandas_series(data[col]) for col in data.columns):
            # Convert via NumPy directly, no PyArrow needed.
            return pl.DataFrame(
                {str(col): data[col].to_numpy() for col in data.columns},
                schema=schema,
                strict=strict,
                schema_overrides=schema_overrides,
                nan_to_null=nan_to_null,
            )._df

    if not _PYARROW_AVAILABLE:
        msg = (
            "pyarrow is required for converting a pandas dataframe to Polars, "
            "unless each of its columns is a simple numpy-backed one "
            "(e.g. 'int64', 'bool', 'float32' - not 'Int64')"
        )
        raise ImportError(msg)
    arrow_dict = {}
    length = data.shape[0]

    if convert_index:
        for idxcol in data.index.names:
            arrow_dict[str(idxcol)] = plc.pandas_series_to_arrow(
                # get_level_values accepts `int | str`
                # but `index.names` returns `Hashable`
                data.index.get_level_values(idxcol),  # type: ignore[arg-type, unused-ignore]
                nan_to_null=nan_to_null,
                length=length,
            )

    for col_idx, col_data in data.items():
        arrow_dict[str(col_idx)] = plc.pandas_series_to_arrow(
            col_data, nan_to_null=nan_to_null, length=length
        )

View on GitHub (pinned to df599052da)

Solutions

  1. Install pyarrow: `pip install pyarrow` (or declare the `polars[pandas]` extra)
  2. If pyarrow is truly impossible, cast every non-simple column to a numpy-backed dtype first: `df["a"] = df["a"].astype("int64")` (after fillna), `df["cat"] = df["cat"].astype(str)`, tz-naive via `dt.tz_localize(None)`
  3. Audit dtypes before conversion: `df.dtypes` — anything that is not a plain numpy dtype needs either casting or pyarrow

Example fix

# before
import pandas as pd, polars as pl
pdf = pd.DataFrame({"a": pd.array([1, None], dtype="Int64")})
pl.from_pandas(pdf)  # ImportError: pyarrow is required for converting a pandas dataframe to Polars ...

# after (option 1)
# pip install pyarrow
pl.from_pandas(pdf)

# after (option 2 — cast to simple numpy dtype)
pdf["a"] = pdf["a"].fillna(0).astype("int64")
pl.from_pandas(pdf)
Defensive patterns

Strategy: validation

Validate before calling

import importlib.util
import numpy as np
import pandas as pd

def simple_numpy_backed(df: pd.DataFrame) -> bool:
    return all(isinstance(df[c].dtype, np.dtype) and df[c].dtype.kind in "biufcMm" for c in df.columns)

if not importlib.util.find_spec("pyarrow") and not simple_numpy_backed(df):
    raise RuntimeError("install pyarrow or cast nullable/categorical/object columns to numpy dtypes")

Type guard

import importlib.util
import numpy as np
import pandas as pd

def convertible_without_pyarrow(df: pd.DataFrame) -> bool:
    """True if every column is a plain numpy-backed dtype polars can read directly."""
    return all(isinstance(df[c].dtype, np.dtype) for c in df.columns) and not any(
        isinstance(df[c].dtype, pd.CategoricalDtype) for c in df.columns
    )

def pyarrow_available() -> bool:
    return importlib.util.find_spec("pyarrow") is not None

Try / catch

try:
    pldf = pl.from_pandas(df)
except ImportError as e:
    if "pyarrow" not in str(e):
        raise
    df = df.convert_dtypes(dtype_backend="numpy") if hasattr(df, "convert_dtypes") else df
    pldf = pl.from_pandas(df.astype({c: "int64" for c in df.select_dtypes("Int64")}))

Prevention

When it happens

Trigger: `pl.from_pandas(df)` (or DataFrame(df)) without pyarrow installed while df contains pandas nullable dtypes ('Int64', 'boolean', 'string[python]'), 'category', tz-aware datetime64[ns, tz], or object columns; the same call succeeds without pyarrow only if every column is plain numpy-backed.

Common situations: Slim production images installing polars without extras; a merge/astype upstream silently changed a column from int64 to nullable Int64, breaking a previously working conversion; pandas code adopting nullable dtypes while the deployment never needed pyarrow before.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/1e51bb4672a1b8f4. Report an issue: GitHub.