{"record":{"id":"50e529ceb0b56c5d","repo":"pola-rs/polars","slug":"column-nm-r-appears-more-than-once-in-the-query","errorCode":null,"errorMessage":"column {nm!r} appears more than once in the query/result cursor","messagePattern":"column (.+?) appears more than once in the query/result cursor","errorType":"exception","errorClass":"DuplicateError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/io/database/_executor.py","lineNumber":356,"sourceCode":"        self,\n        description: list[tuple[str, Any]],\n        schema_overrides: SchemaDict,\n    ) -> SchemaDict:\n        \"\"\"\n        Attempt basic dtype inference from a cursor description.\n\n        Notes\n        -----\n        This is limited; the `type_code` description attr may contain almost anything,\n        from strings or python types to driver-specific codes, classes, enums, etc.\n        We currently only do the additional inference from string/python type values.\n        (Further refinement will require per-driver module knowledge and lookups).\n        \"\"\"\n        dupe_check = set()\n        for nm, desc in description:\n            if nm in dupe_check:\n                msg = f\"column {nm!r} appears more than once in the query/result cursor\"\n                raise DuplicateError(msg)\n            elif desc is not None and nm not in schema_overrides:\n                dtype = dtype_from_cursor_description(desc)\n                if dtype is not None:\n                    schema_overrides[nm] = dtype  # type: ignore[index]\n            dupe_check.add(nm)\n\n        return schema_overrides\n\n    @staticmethod\n    def _is_alchemy_async(conn: Any) -> bool:\n        \"\"\"Check if the given connection is SQLALchemy async.\"\"\"\n        try:\n            from sqlalchemy.ext.asyncio import (\n                AsyncConnection,\n                AsyncSession,\n                async_sessionmaker,\n            )\n","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/io/database/_executor.py#L338-L374","documentation":"While injecting inferred dtypes, ConnectionExecutor._inject_type_overrides walks the cursor description (name, type_code) pairs; if the same column name appears twice in the result set, it raises DuplicateError - a polars exception - because a DataFrame cannot hold two columns with one name. The duplicate always originates in the SQL: SELECT a, a or joins returning identically-named columns without aliases.","triggerScenarios":"pl.read_database('SELECT id, name, id FROM t', connection=conn); SELECT o.id, c.id FROM orders o JOIN customers c ... without aliasing; SELECT * from two tables sharing column names; SurrealDB/other drivers echoing a field twice.","commonSituations":"Ad-hoc joins built by string concatenation; SELECT * on wide join views; generated SQL where aliasing was forgotten; analytics views exposing duplicated metadata columns.","solutions":["Alias every duplicated column in the SELECT list: SELECT o.id AS order_id, c.id AS customer_id","Replace SELECT * with an explicit column list","For dynamic SQL, programmatically de-duplicate names by appending _1, _2 suffixes when building the query"],"exampleFix":"-- before\nSELECT o.id, c.id, o.total FROM orders o JOIN customers c ON o.cust_id = c.id\n\n-- after\nSELECT o.id AS order_id, c.id AS customer_id, o.total\nFROM orders o JOIN customers c ON o.cust_id = c.id","handlingStrategy":"validation","validationCode":"def dedupe_sql_columns(sql: str, describe_fn) -> str:\n    names = [d[0] for d in describe_fn(sql)]  # e.g. cursor.description probe\n    seen: set[str] = set()\n    return sql  # build SELECT with AS aliases when len(names) != len(set(names))\n\n# simpler: always alias join columns explicitly\nQUERY = 'SELECT o.id AS order_id, c.id AS customer_id FROM orders o JOIN customers c ON o.cust_id = c.id'","typeGuard":null,"tryCatchPattern":"from polars.exceptions import DuplicateError\n\ntry:\n    df = pl.read_database(query, connection=conn)\nexcept DuplicateError as err:\n    dupes = {m for m in re.findall(r\"'([^']+)'\", str(err))}\n    raise ValueError(f'alias these duplicated columns in SQL: {dupes}') from err","preventionTips":["Never use SELECT * on joins - list and alias columns explicitly","For generated SQL, add an aliasing step that suffixes repeated names (_1, _2)","Lint queries for duplicate output names before execution in CI"],"tags":["polars","database","sql","duplicate-columns","duplicateerror"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}