1. Severity of the issue: (select one)
None: I’m just curious or want clarification.
Low: Annoying but doesn’t hinder my work.
Medium: Significantly affects my productivity but can find a workaround.
High: Completely blocks me.
2. Environment:
- Ray version: 2.54.0
- Python version: 3.12
- OS: Ubuntu 24.04
- Cloud/Infrastructure: Hetzner cloud
- Other libs/tools (if relevant):
3. What happened vs. what you expected:
-
Expected:
Ray tasks get dispatched (move fromPENDING_NODE_ASSIGNMENTtoRUNNINGor similar) when cluster resources are available, and all tasks in the job get attempted. -
Actual:
Running a batch workload that dispatches ~250-450 near-identical@ray.remotetasks from a single driver in one burst, a subset of those tasks get stuck permanently inPENDING_NODE_ASSIGNMENTand are never scheduled — while hundreds of sibling tasks with identical resource requirements, submitted around the same time, get scheduled normally, run, and complete.The affected tasks:
- Show
node_id: None,worker_id: None,attempt_number: 0inray.util.state.list_tasks()output — never assigned a node, never retried, not even once. - Have
required_resources,runtime_env_info, and argument sizes indistinguishable from sibling tasks that schedule fine (see “What we ruled out”). - Remain stuck for the entire remaining duration of a run (many hours), even as cluster-wide CPU utilization goes to 0.
- Are never flagged by Ray’s own infeasibility tracking (
Infeasible queue length: 0in raylet state dumps throughout).
- Show
4. Attempted workaround
We built an application-level mitigation: detect a task that’s been PENDING_NODE_ASSIGNMENT for >90s while a node genuinely has enough free CPU for it (computed per-node, not from ray.available_resources()'s cluster-wide sum — see below), then ray.cancel(ref, force=True) it and immediately resubmit via .remote() again, which gives it a brand-new task_id. This does not help. In one production run, a specific set of ~20 tasks (identifiable by their arguments, which encode a stable identity — see next section) were cancelled and resubmitted repeatedly.
5. Things we we ruled out
- Not
SPREAD-specific. testedscheduling_strategy="SPREAD"vs default hybrid policy in production. Both produced the same pattern. - Not resource-shape specific. Tested
{CPU: 10, memory: 12GiB}vs{CPU: 10}only. Both hit the identical bug. - Not tied to the pending-task submission cap. Tried limiting the number of dispatched tasks to at most 150, 200, and 500. All produced the same results.
- Not accumulated GCS/raylet state. Fully restarted the cluster (new GCS process, new node IDs across all 20 nodes) between occurrences. The bug reproduced again on the fresh cluster.
- Not duplicate/misconfigured node IPs. Checked
ray.nodes()[*].NodeManagerAddressacross all 20 nodes; all unique. - Not a custom-resource or env-var override. All 19 worker nodes report identical
CPU=32.0,memory=126.4GB, zero custom resources, noRAY_*scheduler-related env var overrides. - Not a worker/node crash. Checked
ray.util.state.list_tasks()forWORKER_DIEDor any error-classified task in the affected job’s actual execution window — zero. - Not large task arguments. Checked
ray.util.state.list_objects()for anything associated with these tasks exceeding ~500KB; found nothing — arguments should be well within the normal inlining path. - Not an unusual resource request.
required_resourcesandruntime_env_infofor stuck tasks (vialist_tasks(detail=True)) are byte-for-byte identical in shape to tasks that scheduled fine ({'CPU': 10.0}, sameruntime_env_info, noplacement_group_id, nolabel_selector). - No raylet-level signal. Grepped the head node’s raylet log for
spillback,lease request, andinfeasiblearound the creation-time window of stuck tasks. Zero matches outside routine periodic state-dump headers. - No GCS-level signal. Same result searching
gcs_server.out. - Autoscaling is not a factor. Cluster uses the Ray
readonlyautoscaler provider (max_workers: 0), a static externally-provisioned pool; no node-launch dynamics apply.