pola-rs/polars · error

duplicate column names found: {series.columns.tolist()!s}

Error message

duplicate column names found: {series.columns.tolist()!s}

What it means

is_simple_numpy_backed_pandas_series checks len(series.shape) > 1 to detect that a "Series" is actually a 2-D pandas DataFrame — which happens when the source DataFrame contains duplicated column labels and one of them is selected with df["a"]. polars raises this ValueError rather than guessing which duplicate you meant.

Source

Thrown at py-polars/src/polars/_utils/construction/utils.py:118

def contains_nested(value: Any, is_nested: Callable[[Any], bool]) -> bool:
    """Determine if value contains (or is) nested structured data."""
    if is_nested(value):
        return True
    elif isinstance(value, dict):
        return any(contains_nested(v, is_nested) for v in value.values())
    elif isinstance(value, (list, tuple)):
        return any(contains_nested(v, is_nested) for v in value)
    return False


def is_simple_numpy_backed_pandas_series(
    series: pd.Series[Any] | pd.Index[Any] | pd.DatetimeIndex,
) -> bool:
    if len(series.shape) > 1:
        # Pandas Series is actually a Pandas DataFrame when the original DataFrame
        # contains duplicated columns and a duplicated column is requested with df["a"].
        msg = f"duplicate column names found: {series.columns.tolist()!s}"  # type: ignore[union-attr]
        raise ValueError(msg)
    return (str(series.dtype) in PANDAS_SIMPLE_NUMPY_DTYPES) or (
        series.dtype == "object"
        and not series.hasnans
        and not series.empty
        and isinstance(next(iter(series)), str)
    )

View on GitHub (pinned to df599052da)

Solutions

  1. Deduplicate labels first: df = df.loc[:, ~df.columns.duplicated()].
  2. Disambiguate manually: df.loc[:, df.columns == "a"].iloc[:, k].
  3. Rename after concat/join so every label is unique before any conversion.

Example fix

// before
pl.from_pandas(pdf["qty"])  # "qty" appears twice in pdf

// after
pdf = pdf.loc[:, ~pdf.columns.duplicated()]
pl.from_pandas(pdf["qty"])
Defensive patterns

Strategy: validation

Validate before calling

if not pdf.columns.is_unique:
    dupes = pdf.columns[pdf.columns.duplicated()].tolist()
    raise ValueError(f"duplicate pandas column labels: {dupes}")
s = pl.Series(pdf[col])

Type guard

def pandas_columns_unique(pdf: pd.DataFrame) -> bool:
    return bool(pdf.columns.is_unique)

Try / catch

try:
    out = pl.from_pandas(pdf[col])
except ValueError as e:
    if "duplicate column names found" in str(e):
        out = pl.from_pandas(pdf.loc[:, ~pdf.columns.duplicated()][col])
    else:
        raise

Prevention

When it happens

Trigger: pl.Series(df["a"]) / pl.from_pandas(df["a"]) where the pandas frame has two columns labeled "a"; duplicate labels created by pd.concat(axis=1), joins, or renames.

Common situations: Joining frames that share column names without suffixes; CSVs with repeated headers; feeding df[col] from a loop over column names into polars.

Related errors


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