matplotlib/matplotlib · error · ValueError

colLabels cannot be used alongside Pandas DataFrame

Error message

colLabels cannot be used alongside Pandas DataFrame

What it means

The DataFrame branch of table() also adopts df.columns as colLabels; passing colLabels together with a pandas DataFrame raises ValueError (table.py:769). Same contract as rowLabels: a DataFrame must own its labels, an array must be given them explicitly.

Source

Thrown at lib/matplotlib/table.py:769

    # Check we have some cellText
    if cellText is None:
        # assume just colours are needed
        rows = len(cellColours)
        cols = len(cellColours[0])
        cellText = [[''] * cols] * rows

    # Check if we have a Pandas DataFrame
    if _is_pandas_dataframe(cellText):
        # if rowLabels/colLabels are empty, use DataFrame entries.
        # Otherwise, throw an error.
        if rowLabels is None:
            rowLabels = cellText.index
        else:
            raise ValueError("rowLabels cannot be used alongside Pandas DataFrame")
        if colLabels is None:
            colLabels = cellText.columns
        else:
            raise ValueError("colLabels cannot be used alongside Pandas DataFrame")
        # Update cellText with only values
        cellText = cellText.values

    rows = len(cellText)
    cols = len(cellText[0])
    for row in cellText:
        if len(row) != cols:
            raise ValueError(f"Each row in 'cellText' must have {cols} "
                             "columns")

    if cellColours is not None:
        if len(cellColours) != rows:
            raise ValueError(f"'cellColours' must have {rows} rows")
        for row in cellColours:
            if len(row) != cols:
                raise ValueError("Each row in 'cellColours' must have "
                                 f"{cols} columns")
    else:

View on GitHub (pinned to b379c1b69e)

Solutions

  1. Drop colLabels — df.columns is used automatically
  2. Or pass plain values: ax.table(cellText=df.values, colLabels=list(df.columns))
  3. When renaming is the goal, rename on the DataFrame first: df.rename(columns=...) then ax.table(cellText=df)

Example fix

# before
ax.table(cellText=df, colLabels=list(df.columns))  # ValueError: colLabels cannot ...

# after: the DataFrame's own columns are used
ax.table(cellText=df)
Defensive patterns

Strategy: validation

Validate before calling

def safe_table(ax, cellText=None, colLabels=None, **kw):
    if _is_pandas_dataframe(cellText) and colLabels is not None:
        raise ValueError(
            'colLabels conflicts with a DataFrame; its columns are used automatically — '
            'pass cellText=df.values to keep custom labels')
    return ax.table(cellText=cellText, colLabels=colLabels, **kw)

Type guard

def is_dataframe(v) -> bool:
    return hasattr(v, 'iloc') and hasattr(v, 'columns')

Try / catch

try:
    ax.table(cellText=data, colLabels=col_labels)
except ValueError as e:
    if 'colLabels' in str(e) and is_dataframe(data):
        col_labels = None                      # DataFrame owns the labels
        ax.table(cellText=data, colLabels=col_labels)
    else:
        raise

Prevention

When it happens

Trigger: ax.table(cellText=df, colLabels=['a', 'b', 'c']); helpers that always set colLabels from an external schema, then receive DataFrames that already carry column names.

Common situations: Schema-driven report generators passing column names that duplicate df.columns; refactoring list input to DataFrames without removing the label arguments.

Related errors


AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21). Data as JSON: /api/errors/527246a20db102df. Report an issue: GitHub.