{"record":{"id":"ea8e0ba3b778dd98","repo":"pola-rs/polars","slug":"unevenly-chunked-columns-must-be-rechunked","errorCode":null,"errorMessage":"unevenly chunked columns must be rechunked","messagePattern":"unevenly chunked columns must be rechunked","errorType":"exception","errorClass":"CopyNotAllowedError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/interchange/dataframe.py","lineNumber":227,"sourceCode":"    def _get_chunks_from_col_chunks(self) -> Iterator[DataFrame]:\n        \"\"\"\n        Return chunks of this dataframe according to the chunks of the first column.\n\n        If columns are not all chunked identically, they will be rechunked like the\n        first column. If copy is not allowed, this raises a RuntimeError.\n        \"\"\"\n        col_chunks = self.get_column(0).get_chunks()\n        chunk_sizes = [chunk.size() for chunk in col_chunks]\n        starts = [0] + list(accumulate(chunk_sizes))\n\n        for i in range(len(starts) - 1):\n            start, end = starts[i : i + 2]\n            chunk = self._df[start:end, :]\n\n            if not all(x == 1 for x in chunk.n_chunks(\"all\")):\n                if not self._allow_copy:\n                    msg = \"unevenly chunked columns must be rechunked\"\n                    raise CopyNotAllowedError(msg)\n                chunk = chunk.rechunk()\n\n            yield chunk\n","sourceCodeStart":209,"sourceCodeEnd":231,"githubUrl":"https://github.com/pola-rs/polars/blob/9b5d73fd00236295624374b075d16b1fe6ec6df9/py-polars/src/polars/interchange/dataframe.py#L209-L231","documentation":"Raised while slicing an interchange frame into chunks aligned with the first column's chunk boundaries. If the row slice has columns with more than one chunk each (uneven or multi-chunk columns), Polars must call rechunk() on the slice, which copies memory; when the interchange object was created with allow_copy=False, CopyNotAllowedError (a RuntimeError) is raised instead.","triggerScenarios":"Iterating icdf.get_chunks() (or get_columns path) on a PolarsDataFrame created via df.__dataframe__(allow_copy=False) or PolarsDataFrame(df, allow_copy=False) where the frame's columns are chunked or unevenly chunked — typical after pl.concat/hstack of separately built Series, or after chunked scans without rechunk.","commonSituations":"Zero-copy pipelines that set allow_copy=False to guarantee no allocation; frames assembled from multiple sources where each column carries its own chunk layout; per-column chunk counts differing (df.n_chunks('all') not all 1).","solutions":["Rechunk the source first: df = df.rechunk() before creating the interchange object with allow_copy=False.","Allow copies: create the interchange object with __dataframe__(allow_copy=True) (the default).","In consumer code, catch CopyNotAllowedError and retry the operation with allow_copy=True."],"exampleFix":"# before\nicdf = df.__dataframe__(allow_copy=False)  # CopyNotAllowedError when columns are chunked\n\n# after\nicdf = df.rechunk().__dataframe__(allow_copy=False)\n# or simply allow the copy:\nicdf = df.__dataframe__(allow_copy=True)","handlingStrategy":"fallback","validationCode":"if df.n_chunks() > 1:  # uneven or multi-chunk columns force a rechunk copy\n    df = df.rechunk()\nicdf = df.__dataframe__(allow_copy=False)","typeGuard":null,"tryCatchPattern":"from polars.interchange.protocol import CopyNotAllowedError\n\ntry:\n    icdf = df.__dataframe__(allow_copy=False)\n    chunks = list(icdf.get_chunks())\nexcept CopyNotAllowedError:\n    icdf = df.rechunk().__dataframe__(allow_copy=True)\n    chunks = list(icdf.get_chunks())","preventionTips":["Rechunk (or pl.concat(..., rechunk=True)) any frame before a zero-copy interchange handoff.","Check df.n_chunks('all') in tests to catch uneven chunk layouts early.","Reserve allow_copy=False for single-chunk frames; treat CopyNotAllowedError as the signal to relax it."],"tags":["polars","interchange-protocol","allow-copy","rechunk","copynotallowederror"],"backgroundTag":"copy-not-allowed","analyzedSha":"9b5d73fd00236295624374b075d16b1fe6ec6df9","analyzedAt":"2026-08-19T12:15:06.350Z","contentChangedAt":"2026-08-19T12:15:06.350Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}