Skip to content

GPU duplicate sort keys with opposite directions fail after a projection #30322

Open

Description

@asddfl

Checks

  • I have checked that this issue has not already been reported.
  • I have confirmed this bug exists on the latest version of Polars.

Reproducible example

import polars as pl

t0 = pl.LazyFrame({"c0": [1.0]})

result = t0.sort(["c0", "c0"], descending=[False, True]).select(pl.col("c0").alias("c1"))

print("CPU Result:")
print(result.collect())

print("GPU Result:")
print(result.collect(engine=pl.GPUEngine(raise_on_fail=True)))

Log output

CPU Result:
shape: (1, 1)
┌─────┐
│ c1  │
│ --- │
│ f64 │
╞═════╡
│ 1.0 │
└─────┘
GPU Result:
  + Exception Group Traceback (most recent call last):
  |   File "/test.py", line 11, in <module>
  |     print(result.collect(engine=pl.GPUEngine(raise_on_fail=True)))
  |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/polars/_utils/deprecation.py", line 97, in wrapper
  |     return function(*args, **kwargs)
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/polars/lazyframe/opt_flags.py", line 361, in wrapper
  |     return function(*args, **kwargs)
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/polars/lazyframe/frame.py", line 2591, in collect
  |     return engine_.collect(
  |            ^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/polars/lazyframe/engine.py", line 443, in collect
  |     return wrap_df(ldf.collect(self.name, callback))
  |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/callback.py", line 321, in _callback
  |     return evaluate_streaming(ir, config_options)
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/parallel.py", line 263, in evaluate_streaming
  |     result, _ = evaluate_logical_plan(ir, config_options, collect_metadata=False)
  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/core.py", line 110, in evaluate_logical_plan
  |     _gpu_result, metadata_collector = evaluate_pipeline_spmd_mode(
  |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/engine/spmd.py", line 153, in evaluate_pipeline_spmd_mode
  |     df, metadata = evaluate_on_rank(
  |                    ^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/engine/core.py", line 961, in evaluate_on_rank
  |     return execute_ir_on_rank(
  |            ^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/engine/core.py", line 672, in execute_ir_on_rank
  |     run_actor_network(ctx, actors=nodes)
  |   File "rapidsmpf/streaming/core/actor.pyx", line 360, in rapidsmpf.streaming.core.actor.run_actor_network
  |   File "rapidsmpf/streaming/core/actor.pyx", line 368, in rapidsmpf.streaming.core.actor.run_actor_network
  |   File "rapidsmpf/streaming/core/actor.pyx", line 365, in rapidsmpf.streaming.core.actor.run_actor_network
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/concurrent/futures/_base.py", line 456, in result
  |     return self.__get_result()
  |            ^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
  |     raise self._exception
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/concurrent/futures/thread.py", line 58, in run
  |     result = self.fn(*self.args, **self.kwargs)
  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "rapidsmpf/streaming/core/actor.pyx", line 267, in rapidsmpf.streaming.core.actor.sync_wait
  |   File "rapidsmpf/streaming/core/actor.pyx", line 262, in rapidsmpf.streaming.core.actor.sync_wait
  |   File "rapidsmpf/streaming/core/actor.pyx", line 263, in rapidsmpf.streaming.core.actor.sync_wait
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/asyncio/runners.py", line 118, in run
  |     return self._loop.run_until_complete(task)
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/asyncio/base_events.py", line 654, in run_until_complete
  |     return future.result()
  |            ^^^^^^^^^^^^^^^
  |   File "rapidsmpf/streaming/core/actor.pyx", line 245, in run_and_publish_task
  |   File "rapidsmpf/streaming/core/actor.pyx", line 172, in run_py_actors
  |   File "/opt/conda/envs/polars-gpu/lib/python3.11/asyncio/taskgroups.py", line 145, in __aexit__
  |     raise me from None
  | ExceptionGroup: unhandled errors in a TaskGroup (2 sub-exceptions)
  +-+---------------- 1 ----------------
    | Exception Group Traceback (most recent call last):
    |   File "rapidsmpf/streaming/core/actor.pyx", line 158, in py_actor
    |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/collectives/sort.py", line 869, in sort_actor
    |     _, local_candidates_list = await gather_in_task_group(
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/utils.py", line 240, in gather_in_task_group
    |     async with asyncio.TaskGroup() as tg:
    |   File "/opt/conda/envs/polars-gpu/lib/python3.11/asyncio/taskgroups.py", line 145, in __aexit__
    |     raise me from None
    | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
    +-+---------------- 1 ----------------
      | Traceback (most recent call last):
      |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/collectives/sort.py", line 508, in _receive_and_buffer_chunks
      |     _select_local_split_candidates(
      |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/sort.py", line 161, in _select_local_split_candidates
      |     return DataFrame.from_table(
      |            ^^^^^^^^^^^^^^^^^^^^^
      |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/containers/dataframe.py", line 247, in from_table
      |     raise ValueError("Mismatching name and table length.")
      | ValueError: Mismatching name and table length.
      +------------------------------------
    +---------------- 2 ----------------
    | Traceback (most recent call last):
    |   File "rapidsmpf/streaming/core/actor.pyx", line 158, in py_actor
    |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/nodes.py", line 96, in default_node_single
    |     metadata_in = await recv_metadata(ch_in, context)
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/opt/conda/envs/polars-gpu/lib/python3.11/site-packages/cudf_polars/streaming/actor_graph/utils.py", line 717, in recv_metadata
    |     assert msg is not None, f"Expected ChannelMetadata message, got {msg}."
    |            ^^^^^^^^^^^^^^^
    | AssertionError: Expected ChannelMetadata message, got None.
    +------------------------------------

Issue description

A one-row Float64 LazyFrame is sorted by ["c0", "c0"] with descending flags [False, True], then projected to a renamed column c1. CPU collection returns the original value 1.0. GPU collection raises an ExceptionGroup. The supplied traceback includes ValueError: Mismatching name and table length. in the cuDF streaming sort actor and AssertionError: Expected ChannelMetadata message, got None.. Both exceptions occur in the recorded GPU execution.

Expected behavior

GPU collection should complete the sort and projection without internal actor errors, returning one Float64 column c1 containing 1.0, matching CPU collection.

Installed versions

Details
--------Version info---------
Polars:              1.44.2
Index type:          UInt32
Platform:            Linux-6.17.0-29-generic-x86_64-with-glibc2.39
Python:              3.11.17 (main, Oct  7 2026, 00:02:24) [GCC 15.3.0]
Runtime:             rt32

----Optional dependencies----
Azure CLI            <not installed>
adbc_driver_manager  <not installed>
altair               <not installed>
azure.identity       <not installed>
boto3                <not installed>
cloudpickle          <not installed>
connectorx           <not installed>
deltalake            <not installed>
fastexcel            <not installed>
fsspec               <not installed>
gevent               <not installed>
google.auth          <not installed>
great_tables         <not installed>
matplotlib           <not installed>
numpy                2.4.6
openpyxl             <not installed>
pandas               3.0.6
polars_cloud         <not installed>
pyarrow              <not installed>
pydantic             <not installed>
pyiceberg            <not installed>
sqlalchemy           <not installed>
torch                <not installed>
xlsx2csv             <not installed>
xlsxwriter           <not installed>
cuda-bindings            12.9.9
cuda-core                1.2.1
cuda-pathfinder          1.8.3
cuda-toolkit             12.9.2.0
cudf-polars-cu12         26.10.0
cudf-streaming-cu12      26.10.0
cupy-cuda12x             14.2.0
kvikio-cu12              26.10.0
libcudf-cu12             26.10.0
libcudf-streaming-cu12   26.10.0
libkvikio-cu12           26.10.0
librapidsmpf-cu12        26.10.0
librmm-cu12              26.10.0
libucx-cu12              1.21.0
libucxx-cu12             0.52.0
nvidia-cublas-cu12       12.9.2.10
nvidia-cuda-nvrtc-cu12   12.9.86
nvidia-cuda-runtime-cu12 12.9.79
nvidia-cufft-cu12        11.4.1.4
nvidia-cufile-cu12       1.14.1.1
nvidia-curand-cu12       10.3.10.19
nvidia-cusolver-cu12     11.7.5.82
nvidia-cusparse-cu12     12.5.10.65
nvidia-libnvcomp-cu12    5.3.0.16
nvidia-ml-py             13.615.71
nvidia-nvjitlink-cu12    12.9.86
nvtx                     0.2.16
polars                   1.44.2
polars-runtime-32        1.44.2
pylibcudf-cu12           26.10.0
rapids-logger            0.3.0
rapidsmpf-cu12           26.10.0
rmm-cu12                 26.10.0

Activity

  1. added
    bugSomething isn't working
    pythonRelated to Python Polars
    needs triageAwaiting prioritization by a maintainer
    on Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-gpuArea: gpu enginebugSomething isn't workingneeds triageAwaiting prioritization by a maintainerpythonRelated to Python Polars

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions