Textualize/textual · error · DuplicateKey

The column key {key!r} already exists.

Error message

The column key {key!r} already exists.

What it means

Raised by DataTable.add_column when the supplied key (or auto-generated ColumnKey wrapping it) already exists in _column_locations. Column keys must be unique for the lifetime of the table; Textual raises DuplicateKey rather than overwriting.

Source

Thrown at src/textual/widgets/_data_table.py:1635

        default: CellType | None = None,
    ) -> ColumnKey:
        """Add a column to the table.

        Args:
            label: A str or Text object containing the label (shown top of column).
            width: Width of the column in cells or None to fit content.
            key: A key which uniquely identifies this column.
                If None, it will be generated for you.
            default: The  value to insert into pre-existing rows.

        Returns:
            Uniquely identifies this column. Can be used to retrieve this column
                regardless of its current location in the DataTable (it could have moved
                after being added due to sorting/insertion/deletion of other columns).
        """
        column_key = ColumnKey(key)
        if column_key in self._column_locations:
            raise DuplicateKey(f"The column key {key!r} already exists.")
        column_index = len(self.columns)
        label = Text.from_markup(label) if isinstance(label, str) else label
        content_width = measure(self.app.console, label, 1)
        if width is None:
            column = Column(
                column_key,
                label,
                content_width,
                content_width=content_width,
                auto_width=True,
            )
        else:
            column = Column(
                column_key,
                label,
                width,
                content_width=content_width,
            )

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Check if key in table.column_keys (or compare ColumnKey(key)) before adding.
  2. Call table.clear(columns=True) before rebuilding the full column set.
  3. Use unique keys per refresh, e.g. f'{base_key}_{n}'.
  4. Catch DuplicateKey and skip or update the existing column instead.

Example fix

# before
table.add_column('Name', key='name')

# after
if 'name' not in table.column_keys:
    table.add_column('Name', key='name')
Defensive patterns

Strategy: validation

Validate before calling

if key not in table.column_keys:
    table.add_column(label, key=key)

Try / catch

from textual.widgets._data_table import DuplicateKey
try:
    table.add_column(label, key=key)
except DuplicateKey:
    pass  # column already present

Prevention

When it happens

Trigger: Calling add_column(key='name') twice; re-adding columns with explicit keys after data refresh without calling clear() first; generating keys that collide with previously added columns.

Common situations: Refresh routines that call add_column in a loop on every update; using fixed schema keys while old columns still exist; partial clears that remove rows but not columns.

Related errors


AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27). Data as JSON: /api/errors/7422203ec9285b64. Report an issue: GitHub.