{"record":{"id":"a30dd38c0ca43d01","repo":"pola-rs/polars","slug":"cannot-use-glob-patterns-and-integer-based-project","errorCode":null,"errorMessage":"cannot use glob patterns and integer based projection as `columns` argument\n\nUse columns: List[str]","messagePattern":"cannot use glob patterns and integer based projection as `columns` argument\n\nUse columns: List\\[str\\]","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/io/csv/functions.py","lineNumber":721,"sourceCode":"            skip_rows_after_header=skip_rows_after_header,\n            row_index_name=row_index_name,\n            row_index_offset=row_index_offset,\n            eol_char=eol_char,\n            raise_if_empty=raise_if_empty,\n            truncate_ragged_lines=truncate_ragged_lines,\n            decimal_comma=decimal_comma,\n            glob=glob,\n        )\n        if columns is None:\n            return scan._collect_eager()\n        elif is_str_sequence(columns, allow_str=False):\n            return scan.select(columns)._collect_eager()\n        else:\n            msg = (\n                \"cannot use glob patterns and integer based projection as `columns` argument\"\n                \"\\n\\nUse columns: List[str]\"\n            )\n            raise ValueError(msg)\n\n    projection, columns = parse_columns_arg(columns)\n\n    pydf = PyDataFrame.read_csv(\n        source,\n        infer_schema_length,\n        batch_size,\n        has_header,\n        ignore_errors,\n        n_rows,\n        skip_rows,\n        skip_lines,\n        projection,\n        separator,\n        rechunk,\n        columns,\n        encoding,\n        n_threads,","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/io/csv/functions.py#L703-L739","documentation":"When read_csv receives a glob pattern as source, it internally delegates to scan_csv (functions.py:686) and applies selection via LazyFrame.select, which only accepts column names. Integer-based projection (positional column indices) is therefore unsupported on glob sources, because column 0 of each matched file could differ. Passing a list of ints as columns raises this ValueError.","triggerScenarios":"pl.read_csv('data/2024-*.csv', columns=[0, 2]); any source string where is_glob_pattern(source) is true (contains * ? [ ]) combined with an int sequence for columns; also fires when columns is a non-string sequence after the is_str_sequence check fails.","commonSituations":"Seasonal/partitioned exports read as one glob; porting single-file code that used positional columns=[0, 1] to a wildcard path; files whose header names differ across shards so names cannot be used.","solutions":["Select by name instead: columns=['ts', 'value'] (headers must match across all matched files)","Expand the glob yourself and read positionally per file: pl.concat([pl.read_csv(f, columns=[0, 2]) for f in sorted(glob.glob('data/2024-*.csv'))])","Read without columns and slice positionally afterwards: pl.read_csv('data/2024-*.csv').select(pl.nth([0, 2]))"],"exampleFix":"# before\npl.read_csv('data/2024-*.csv', columns=[0, 2])\n\n# after - select by name\npl.read_csv('data/2024-*.csv', columns=['ts', 'value'])\n\n# after - expand glob for positional reads\nimport glob\npl.concat([pl.read_csv(f, columns=[0, 2]) for f in sorted(glob.glob('data/2024-*.csv'))])","handlingStrategy":"validation","validationCode":"import glob as globmod\nfrom polars.utils.various import is_glob_pattern\n\nif is_glob_pattern(source) and columns and isinstance(columns[0], int):\n    files = sorted(globmod.glob(source))\n    df = pl.concat([pl.read_csv(f, columns=columns) for f in files])\nelse:\n    df = pl.read_csv(source, columns=columns)","typeGuard":"def glob_safe_columns(source: str, columns) -> list[str] | None:\n    \"\"\"Reject int projections for glob sources before calling read_csv.\"\"\"\n    if columns and is_glob_pattern(source) and isinstance(columns[0], int):\n        raise TypeError('use column names (or expand the glob) for glob sources')\n    return columns","tryCatchPattern":null,"preventionTips":["Prefer column names over positional indices in any code path that may receive globs","Centralize glob handling: expand files once and read each file positionally, then concat","If shard headers are unreliable, normalize them upstream so name-based selection is safe"],"tags":["polars","csv","glob","projection","valueerror"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}