{"record":{"id":"04a0a4b45cfb6ff5","repo":"pola-rs/polars","slug":"n-chunks-must-be-a-multiple-of-the-number-of-chu-04a0a4","errorCode":null,"errorMessage":"`n_chunks` must be a multiple of the number of chunks of this dataframe ({total_n_chunks})","messagePattern":"`n_chunks` must be a multiple of the number of chunks of this dataframe \\((.+?)\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/interchange/dataframe.py","lineNumber":194,"sourceCode":"        -----\n        When the columns in the dataframe are chunked unevenly, or when `n_chunks` is\n        higher than the number of chunks in the dataframe, a slice must be performed\n        that is not on the chunk boundary. This will trigger some compute for columns\n        that contain null values and boolean columns.\n        \"\"\"\n        total_n_chunks = self.num_chunks()\n        chunks = self._get_chunks_from_col_chunks()\n\n        if (n_chunks is None) or (n_chunks == total_n_chunks):\n            for chunk in chunks:\n                yield PolarsDataFrame(chunk, allow_copy=self._allow_copy)\n\n        elif (n_chunks <= 0) or (n_chunks % total_n_chunks != 0):\n            msg = (\n                \"`n_chunks` must be a multiple of the number of chunks of this\"\n                f\" dataframe ({total_n_chunks})\"\n            )\n            raise ValueError(msg)\n\n        else:\n            subchunks_per_chunk = n_chunks // total_n_chunks\n            for chunk in chunks:\n                size = len(chunk)\n                step = size // subchunks_per_chunk\n                if size % subchunks_per_chunk != 0:\n                    step += 1\n                for start in range(0, step * subchunks_per_chunk, step):\n                    yield PolarsDataFrame(\n                        chunk[start : start + step, :],\n                        allow_copy=self._allow_copy,\n                    )\n\n    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","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/interchange/dataframe.py#L176-L212","documentation":"Raised by PolarsDataFrame.get_chunks when n_chunks is <= 0 or not an integer multiple of the dataframe's actual chunk count. Chunk production derives from column 0's chunks and can only subdivide each evenly, so requests must align with num_chunks().","triggerScenarios":"dfi.get_chunks(4) on a frame with 3 chunks; passing 0 or negative counts; batching logic that requests a consumer-chosen chunk count unrelated to the source chunking.","commonSituations":"Streaming consumers requesting chunks sized to their own batch windows; frames assembled from multiple scans/concats yielding non-divisible chunk counts; interleaving dataframe chunks with per-column get_chunks calls under mismatched assumptions.","solutions":["Call get_chunks() with n_chunks=None and batch on the consumer side","Request a multiple of the frame's chunk count: dfi.num_chunks() * k","Ensure n_chunks > 0 and validated against num_chunks() before requesting"],"exampleFix":"// before\nfor chunk in dfi.get_chunks(7):  # frame has 3 chunks\n    ...\n// after\nfor chunk in dfi.get_chunks():\n    ...  # batch downstream at whatever size you need","handlingStrategy":"validation","validationCode":"total = dfi.num_chunks()\nok = n_chunks is None or (n_chunks > 0 and n_chunks % total == 0)","typeGuard":"def is_valid_df_chunk_request(n_chunks: int, total: int) -> bool:\n    return n_chunks > 0 and n_chunks % total == 0","tryCatchPattern":"try:\n    for chunk in dfi.get_chunks(n_chunks):\n        ...\nexcept ValueError:\n    for chunk in dfi.get_chunks():\n        ...","preventionTips":["Let the producer yield natural chunks; control batching downstream","Recompute num_chunks() whenever the frame is rebuilt"],"tags":["polars","interchange-protocol","chunking","argument-validation"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}