{"record":{"id":"9cae133237bf9f15","repo":"pola-rs/polars","slug":"cannot-create-a-second-col-r-column","errorCode":null,"errorMessage":"cannot create a second {col!r} column","messagePattern":"cannot create a second (.+?) column","errorType":"exception","errorClass":"DuplicateError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/io/spreadsheet/_write_utils.py","lineNumber":247,"sourceCode":"    )\n\n\ndef _xl_inject_dummy_table_columns(\n    df: DataFrame,\n    coldefs: dict[str, Any],\n    *,\n    dtype: dict[str, PolarsDataType] | PolarsDataType | None = None,\n    expr: Expr | None = None,\n) -> DataFrame:\n    \"\"\"Insert dummy frame columns in order to create empty/named table columns.\"\"\"\n    df_original_columns = set(df.columns)\n    df_select_cols = df.columns.copy()\n    cast_lookup = {}\n\n    for col, definition in coldefs.items():\n        if col in df_original_columns:\n            msg = f\"cannot create a second {col!r} column\"\n            raise DuplicateError(msg)\n        elif not isinstance(definition, dict):\n            df_select_cols.append(col)\n        else:\n            cast_lookup[col] = definition.get(\"return_dtype\")\n            insert_before = definition.get(\"insert_before\")\n            insert_after = definition.get(\"insert_after\")\n\n            if insert_after is None and insert_before is None:\n                df_select_cols.append(col)\n            else:\n                insert_idx = (\n                    df_select_cols.index(insert_after) + 1  # type: ignore[arg-type]\n                    if insert_before is None\n                    else df_select_cols.index(insert_before)\n                )\n                df_select_cols.insert(insert_idx, col)\n\n    expr = F.lit(None) if expr is None else expr","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/io/spreadsheet/_write_utils.py#L229-L265","documentation":"polars.exceptions.DuplicateError raised while preparing an Excel write (write_excel) from _xl_inject_dummy_table_columns. Sparklines, column_formulas, and row_totals are realized by injecting placeholder columns into the frame; if one of those definitions uses a column name that already exists in the DataFrame, injecting it would create a duplicate column, which polars forbids.","triggerScenarios":"pl.write_excel(df, sparklines={'total': {'columns': ['q1','q2']}}) when 'total' is already a df column; same for column_formulas={'total': {...}} or row_totals named after an existing column.","commonSituations":"Writing a report whose DataFrame already contains an aggregate column and trying to overlay an in-sheet sparkline/formula with the same header; schemas that evolved (a computed 'total' column was added upstream) breaking a previously working write_excel call.","solutions":["Give the injected column a new, unused name (e.g. 'trend', 'total_x').","Or drop/rename the existing DataFrame column before writing if the sheet column should be formula/sparkline-driven instead of data-driven.","Assert upfront that set(sparklines) | set(column_formulas) | set(row_totals or []) is disjoint from set(df.columns)."],"exampleFix":"# before\npl.write_excel(df, sparklines={'total': {'columns': ['q1', 'q2', 'q3', 'q4']}})  # 'total' already in df\n\n# after\npl.write_excel(df, sparklines={'trend': {'columns': ['q1', 'q2', 'q3', 'q4']}})","handlingStrategy":"validation","validationCode":"injected = set(sparklines or {}) | set(column_formulas or {})\nif row_totals:\n    injected |= {row_totals} if isinstance(row_totals, str) else set(row_totals or [])\nclash = injected & set(df.columns)\nif clash:\n    raise ValueError(f'write_excel placeholder names collide with df columns: {sorted(clash)}')\npl.write_excel(df, sparklines=sparklines, column_formulas=column_formulas, row_totals=row_totals)","typeGuard":null,"tryCatchPattern":"try:\n    pl.write_excel(df, sparklines=sparklines)\nexcept pl.exceptions.DuplicateError as e:\n    if 'cannot create a second' in str(e):\n        # rename the colliding placeholder and retry\n        renamed = {f'{k}_x': v for k, v in sparklines.items() if k in df.columns}\n        pl.write_excel(df, sparklines={**{k: v for k, v in sparklines.items() if k not in df.columns}, **renamed})\n    else:\n        raise","preventionTips":["Choose placeholder names with a suffix convention unlikely to appear in data ('_trend', '_calc').","Assert placeholder names are disjoint from df.columns before every write_excel call.","Re-run report smoke tests whenever upstream schemas add columns."],"tags":["excel","spreadsheet","write-excel","sparklines","duplicate-column"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}