pola-rs/polars · error · ValueError

invalid table style key: {key!r}

Error message

invalid table style key: {key!r}

What it means

ValueError raised by _xl_setup_table_options during write_excel when table_style is a dict containing an unrecognized key. The dict form accepts exactly five keys — 'style', 'banded_columns', 'banded_rows', 'first_column', 'last_column' (mirroring Excel's table style options); anything else is a typo or an option that belongs elsewhere.

Source

Thrown at py-polars/src/polars/io/spreadsheet/_write_utils.py:556

    return table_columns, column_formats, df  # type: ignore[return-value]


def _xl_setup_table_options(
    table_style: dict[str, Any] | str | None,
) -> tuple[dict[str, Any] | str | None, dict[str, Any]]:
    """Setup table options, distinguishing style name from other formatting."""
    if isinstance(table_style, dict):
        valid_options = (
            "style",
            "banded_columns",
            "banded_rows",
            "first_column",
            "last_column",
        )
        for key in table_style:
            if key not in valid_options:
                msg = f"invalid table style key: {key!r}"
                raise ValueError(msg)

        table_options = table_style.copy()
        table_style = table_options.pop("style", None)
    else:
        table_options = {}

    return table_style, table_options


@overload
def _xl_worksheet_in_workbook(
    wb: Workbook, ws: Worksheet, *, return_worksheet: Literal[False] = ...
) -> bool: ...
@overload
def _xl_worksheet_in_workbook(
    wb: Workbook, ws: Worksheet, *, return_worksheet: Literal[True]
) -> Worksheet: ...

View on GitHub (pinned to df599052da)

Solutions

  1. Correct the key name: use only 'style', 'banded_columns', 'banded_rows', 'first_column', 'last_column'.
  2. If you meant the style name itself, pass table_style='Table Style Medium 9' as a plain string.
  3. Keep a frozenset of the valid keys and validate config dicts against it before calling write_excel.

Example fix

# before
pl.write_excel(df, table_style={'style': 'Table Style Medium 9', 'band_rows': True})

# after
pl.write_excel(df, table_style={'style': 'Table Style Medium 9', 'banded_rows': True})
Defensive patterns

Strategy: validation

Validate before calling

VALID_TABLE_STYLE_KEYS = {'style', 'banded_columns', 'banded_rows', 'first_column', 'last_column'}
if isinstance(table_style, dict):
    bad = set(table_style) - VALID_TABLE_STYLE_KEYS
    if bad:
        raise ValueError(f'invalid table_style keys: {sorted(bad)}; valid: {sorted(VALID_TABLE_STYLE_KEYS)}')
pl.write_excel(df, table_style=table_style)

Type guard

def is_valid_table_style(ts: object) -> bool:
    if isinstance(ts, str):
        return True
    return isinstance(ts, dict) and set(ts) <= {'style', 'banded_columns', 'banded_rows', 'first_column', 'last_column'}

Try / catch

try:
    pl.write_excel(df, table_style=table_style)
except ValueError as e:
    if 'invalid table style key' in str(e):
        cleaned = {k: v for k, v in table_style.items() if k in VALID_TABLE_STYLE_KEYS} if isinstance(table_style, dict) else table_style
        pl.write_excel(df, table_style=cleaned)
    else:
        raise

Prevention

When it happens

Trigger: pl.write_excel(df, table_style={'style': 'Table Style Medium 9', 'banded_cols': True}) — misspelled 'banded_columns'; or keys like 'stripe_rows', 'style_name', 'autofilter' that are not part of the API.

Common situations: Hand-writing the options dict from memory of the Excel UI instead of the polars docs; translating openpyxl/xlsxwriter option names into this dict; version drift after the dict-based table_style interface was introduced.

Related errors


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