Skip to content

gds_mt: decode cuFile errors correctly in IO failure logs - #2143

Merged
aranadive merged 4 commits into
ai-dynamo:mainfrom
changhyeonnam:fix/gds-mt-cufile-error-decode
Oct 10, 2026
Merged

aranadive merged 4 commits into
ai-dynamo:mainfrom
changhyeonnam:fix/gds-mt-cufile-error-decode

Conversation

@changhyeonnam

@changhyeonnam changhyeonnam commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

What?

Fix error decoding in runCuFileOp: use strerror(errno) only for plain filesystem errors, and decode cuFile-level errors via CUFILE_ERRSTR with the numeric code included. Follow-up to #2069, which did the equivalent for the cuda_gds plugin, using the same message format.

Why?

cuFileRead/cuFileWrite report filesystem errors as -1 with errno set, and cuFile-level errors either as a negative CUfileOpError return value (as documented in cufile.h) or, as observed in practice, as -1 with the CUfileOpError code stored in errno. The current code prints strerror(errno) for every failure, which produces garbage for cuFile-level errors. Reproduced on a B200 system by forcing a cuFile-level read failure:

before: GDS_MT: cuFileRead failed: Unknown error 5027
after:  GDS_MT: cuFileRead failed: file descriptor is not registered (err=5027)

How?

Added a small file-local helper that branches using the IS_CUFILE_ERR macro from cufile.h, used by both the read and write paths, following the helper pattern suggested in the #2069 review. Plain filesystem error messages are unchanged. Verified the changed lines pass clang-format-19 and the plugin builds cleanly.

Summary by CodeRabbit

  • Bug Fixes
    • Improved error reporting for failed direct storage reads and writes, distinguishing filesystem errors from cuFile errors.

@copy-pr-bot

copy-pr-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown

👋 Hi changhyeonnam! Thank you for contributing to ai-dynamo/nixl.

Your PR reviewers will review your contribution then trigger the CI to test your changes.

🚀

@changhyeonnam

Copy link
Copy Markdown
Contributor Author

Hi, @brminich ! Could you take a look when you get a chance? 😄

@maheshrbapatu

Copy link
Copy Markdown
Contributor

LGTM

@vvenkates27

vvenkates27 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

@changhyeonnam Please can you rebase since there has been a re-org for GDS plugins?

cuFileRead and cuFileWrite report filesystem errors as -1 with errno set, and
cuFile-level errors either as a negative CUfileOpError return value (as
documented) or, as observed in practice, as -1 with the CUfileOpError code
stored in errno. runCuFileOp logged strerror(errno) for every failure, so
cuFile-level errors produced garbage such as "cuFileRead failed: Unknown error
5019".

Decode the return value accordingly: strerror only when errno holds a plain
errno value, CUFILE_ERRSTR with the numeric code otherwise, matching the error
format used by the GDS batch engine. Verified on a B200 system with cuFile
1.15.1.6 by reading through a file opened write-only; the log now reads
"unsupported file open flags (err=5019)" instead of "Unknown error 5019".

Signed-off-by: Changhyeon Nam <changhyeon03@sk.com>
@changhyeonnam
changhyeonnam force-pushed the fix/gds-mt-cufile-error-decode branch from 2a5e078 to a201990 Compare October 1, 2026 15:58
@changhyeonnam

Copy link
Copy Markdown
Contributor Author

Hi @vvenkates27, I rebased onto main. The change is now in gds_mt_engine.cpp, same content. Could you take another look? Thanks!

@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Configuration used: Repository: ai-dynamo/nixl/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Enterprise
  • Run ID: 9fd61636-4882-4c34-8124-eb1a9fffa170

📥 Commits

Reviewing files that changed from the base of the PR and between 8ab9d5d and 42fd117.


You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: ai-dynamo/nixl/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 3456ec5e-7c6c-440f-8563-bc8782a81ed6


📥 Commits

Reviewing files that changed from the base of the PR and between df92e41 and a201990.


📒 Files selected for processing (1)
  • src/plugins/cuda_gds/gds_mt_engine.cpp

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.



📝 Walkthrough

Walkthrough

cuFile read and write failures now use a helper that distinguishes system errors from cuFile errors. Both paths retain their existing backend error status and early return.

Changes

cuFile Error Logging

Layer / File(s) Summary
Classify and log read and write errors
src/plugins/cuda_gds/gds_mt_engine.cpp
A new helper distinguishes filesystem failures from cuFile errors and logs the corresponding error. Failed reads and writes use the helper; their backend error status and early return are unchanged.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix


Merge Risk: ⚪ Minimal · up to a2019

The change improves cuFile failure messages without a supported change to I/O behavior. No merge-blocking risk is identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: correcting cuFile error decoding in GDS multi-threaded I/O failure logs.
Description check ✅ Passed The description includes all required sections. It explains what changed, why the change is needed, and how the helper is implemented. It also includes reproduction details and verification results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.


✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR


  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

@benlwalker

Copy link
Copy Markdown
Contributor

/ok to test a201990

@aranadive

Copy link
Copy Markdown
Contributor

/ok to test b3e0212

@aranadive

Copy link
Copy Markdown
Contributor

/build

@svc-nixl

svc-nixl commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agent — nixl-ci-build-wheel · commit b3e0212a

TL;DR: The build failed in the Allocate Environment stage for the sglang/aarch64 branch because salloc on dlcluster.nvidia.com could not reach the slurm controller (slurm_load_partitions error: Socket timed out on send/recv operation → Connection reset by peer); this is a cluster/CI infrastructure failure unrelated to PR #2143, so the job should simply be retried once the slurm controller is healthy.

Full analysis

Summary: Stage 588 Allocate Environment (branch build_helper_sglang/aarch64/python_3.12) failed after salloc was rejected by the slurm head node; the parallel build_helper_vllm branch then also failed to obtain a Jenkins k8s agent due to an exhausted CPU resource quota.

Root cause: Two independent infrastructure problems, neither in nixl code:

  1. Slurm control plane unavailable. At 17:51:30 the pipeline ran:
    salloc -N 1 -p gb200nvl72_ci --job-name=nixl-ci-build-wheel-sglang-2079 --immediate=3600 --time=01:30:00 --no-shell --account=oberon-gb-ci
    and 56 s later got:

    slurm_load_partitions error: Socket timed out on send/recv operation
    salloc: error: cli_filter_p_pre_submit/lua: /etc/slurm/cli_filter.lua:48: attempt to index local 'line' (a nil value)
    salloc: error: Job submit/allocate failed: Connection reset by peer
    

    The RPC to slurmctld timed out; the site-local cli_filter.lua then crashed on line 48 because it indexes a line value derived from the (now empty) partition query, masking the real error. Note this is not a timeout/hang of the build — the gap between log lines is under a minute and the earlier vLLM branch allocated job 2425909 on gb200-nvl4-ts2-92 successfully at 17:30, so the controller degraded between 17:30 and 17:51.

  2. Kubernetes quota exhaustion. After the error propagated, the pipline stop on build_helper_vllm node could not be scheduled for ~11 retries:
    pods "nixl-ci-build-wheel-buildhelpervllm-2079-..." is forbidden: exceeded quota: resourcequota-nbu-swx-nixl, requested: cpu=16500m, used: cpu=236400m, limited: cpu=240
    The namespace was at 236.4/240 CPU, and each build-helper pod requests 16.5 CPU, so no pod could fit.

All actual build work succeeded: three Build Wheel stages passed, nixl_cu13-1.6.0-cp312-cp312-manylinux_2_28_aarch64.whl was built, repaired by auditwheel, installed, and pushed as ci/pr/aarch64/sglang-nixl:2079. The Run vLLM sanity stage also passed. Nothing touched by this PR (GDS/cuFile error decoding) was exercised by the failing stage.

Implicated commit: none — commit b3e0212 (branch fix/gds-mt-cufile-error-decode, PR #2143) is not implicated. The failure is in cluster infrastructure (/etc/slurm/cli_filter.lua on dlcluster, which lives outside this repo) and in the Jenkins k8s namespace quota.

File: /etc/slurm/cli_filter.lua:48 (cluster-side, not in repo); quota object resourcequota-nbu-swx-nixl in namespace nbu-swx-nixl

Suggested fix:

  1. Retry build plugins/uccl: adopt variable-length notification API #2079 — the wheel build and vLLM sanity already passed, and the allocation failure is transient.
  2. Ask the dlcluster admins to check slurmctld health/responsiveness around 2026-10-08 17:51 UTC on partition gb200nvl72_ci, and to make cli_filter.lua:48 nil-safe so a controller RPC timeout surfaces as a clear "controller unreachable" message instead of a lua index error.
  3. Make the CI slurm.allocation helper retry salloc on transient controller errors (Socket timed out on send/recv, Connection reset by peer) rather than failing the branch immediately — the --immediate=3600 only covers resource waiting, not RPC failure.
  4. Reduce concurrency or raise the namespace CPU quota: with a 240-CPU limit and 16.5-CPU build-helper pods, the parallel matrix (6+ Build Docker branches plus three Build Wheel branches) saturates the quota and the pipeline_stop cleanup node cannot even be scheduled — consider lowering the parallel branch count or giving the cleanup pod a small resource request so teardown always fits.

Related: none found — issue/PR search for this error signature failed to return results.

@svc-nixl

svc-nixl commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agent — nixl-ci-gpu · commit b3e0212a

TL;DR: The build failed in the "Allocate Environment" stage because scctl could not log in — the TCP connection to the Rancher Azure-AD auth endpoint (10.220.0.21:443) timed out after 4 retries, so no slurm GPU allocation was ever made. This is a CI infrastructure/network failure, not a code defect in PR #2143; retry the build and have IT check reachability of the Rancher endpoint from the Jenkins k8s agents.

Full analysis

Summary: Stage 164 "Allocate Environment" failed: scctl login to the Rancher auth service timed out, so the mizu partition slurm allocation (nixl-ci-gpu-3942) never started.

Root cause: The pipeline calls slurm.allocation(partition: mizu, headNode: scctl, jobName: nixl-ci-gpu-3942, ...), which first runs scctl upgrade/login. That login failed with:

Error: failed to get token: error sending rancher token request to
https://rancher-swx-k8s-mec.mec01.labs.mlnx.nvidia.com/v3-public/azureADProviders/azuread?action=login:
request failed after 4 retries: ... dial tcp 10.220.0.21:443: connect: connection timed out

The ~7-minute gap between 17:28:43 (the slurm.allocation call) and 17:35:35 (the error) is fully accounted for by 4 sequential TCP connect timeouts to that endpoint — the tool was blocked on network I/O, not hung in a nixl process. Everything before this succeeded: the Docker image built, all 316 ninja targets compiled and linked, nixlbench built, and the image was pushed to artifactory as nixl-ci-gpu-test:3942. No test ever executed, and the cleanup stage confirms nothing was allocated: WARNING: No job ID files found in /mnt/pvc/nixl-ci-gpu/.

The commit under test (b3e0212, fix/gds-mt-cufile-error-decode) is not implicated — the failure occurs in the Jenkins shared library (swx-jenkins-lib → slurm.allocation) before any nixl code is run on a GPU node.

Implicated commit: none — infrastructure failure, unrelated to [REDACTED:Hex High Entropy String]

File: Jenkins pipeline stage "Allocate Environment" (swx-jenkins-lib slurm.allocation, credentialsId svc-nixl-scctl); no nixl source file involved

Suggested fix:

  1. Re-run build #3942 — this class of failure is transient and the build artifacts up to the test stage were all produced successfully.
  2. If it reproduces, escalate to CI/IT: verify that rancher-swx-k8s-mec.mec01.labs.mlnx.nvidia.com (10.220.0.21:443) is reachable from the nbu-swx-nixl Kubernetes namespace — check for a firewall/route change, a down Rancher ingress, or a stale DNS→IP mapping for that host.
  3. Hardening suggestion for the pipeline: wrap the slurm.allocation step in a retry(2) and surface the scctl login as a distinct pre-flight check, so an auth-endpoint outage fails fast (seconds) with a clear "infra" classification instead of burning ~7 minutes inside the allocation step and reporting as a generic script returned exit code 1.

Related: none

🛡️ This comment had 1 potential secret(s) redacted (Hex High Entropy String). See request_id 9f19ee91-f935-4581-8472-e45e6535c3af in the triage console for the audit trail.

@svc-nixl

svc-nixl commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

🤖 CI Triage Agent — nixl-ci-gpu-vr · commit b3e0212a

TL;DR: The build didn't fail on code — the "Allocate Environment" stage spent the full hour of its --immediate=3600 window waiting for a slurm allocation on partition vrnvl72 and gave up ("Unable to allocate resources: Connection timed out"). This is a partition-capacity/scheduling problem, not a defect in PR #2143; re-run once the Vera Rubin partition has free nodes.

Full analysis

Summary: nixl-ci-gpu-vr #166 failed in stage Allocate Environment (node 164): salloc for job name nixl-ci-gpu-vr-166 could not obtain resources and exited non-zero, aborting the parallel branch build_helper_dl/aarch64/1.

Root cause: All build work succeeded — "Compiling NIXL Docker Image" finished, meson/ninja built nixl and nixlbench cleanly, and the PR test image nixl-ci-gpu-vr-test:166 was built and pushed at 17:08. The pipeline then called slurm.allocation with immediateTimeout:3600:

  • 17:08:21 — ssh ... salloc -N 1 -p vrnvl72 --job-name=nixl-ci-gpu-vr-166 --immediate=3600 --time=01:30:00 --no-shell --account=rubin --gres=gpu:2 --mem=128G --mincpus=24 --exclude=vr-nvl72-ts3-l06-comp137,...comp139,...comp141,vr-nvl72-ts2b-l10-comp102
  • 18:08:29 — salloc: Pending job allocation 2425807 / job 2425807 queued and waiting for resources / salloc: error: Unable to allocate resources: Connection timed out

The single 60-minute gap between those two lines is exactly the --immediate=3600 budget, and the slurm messages state plainly that the job was queued waiting for resources the whole time — so nothing hung inside the job; the scheduler simply never had a matching node. The "Connection timed out" text is slurm's wording when the --immediate deadline expires, not a network fault. The request is also narrowed on both sides: it wants --gres=gpu:2 --mem=128G --mincpus=24 on vrnvl72 while four nodes in that partition are blacklisted by --exclude, leaving a small candidate set that was fully busy. Nothing in the fix/gds-mt-cufile-error-decode branch is implicated — the GDS/cuFile code compiled fine and no test ever ran.

Implicated commit: No code commit — infrastructure/scheduling. Contributing CI config changes: 1f87bd7b (NirWolfer, "CI: exclude misconfigured Vera Rubin nodes from nixl-ci-gpu-vr", #2339) which removed four vrnvl72 nodes from the candidate pool, and [REDACTED:Hex High Entropy String] (NirWolfer, "CI: request 2 GPUs instead of a whole node", #2352).

File: Jenkins pipeline config for nixl-ci-gpu-vr — the slurm.allocation call with immediateTimeout:3600 and the extraArgs --gres=gpu:2 --mem=128G --mincpus=24 --exclude=vr-nvl72-ts3-l06-comp137,vr-nvl72-ts3-l06-comp139,vr-nvl72-ts3-l06-comp141,vr-nvl72-ts2b-l10-comp102 (build log, "Allocate Environment" stage, lines 2–7)

Suggested fix: Re-trigger the build — this is retryable and unrelated to the PR. To stop it recurring: (1) have the allocation step distinguish "no resources available" from a real failure and either retry with backoff or mark the GPU-VR branch unstable/skipped instead of failing the whole PR build, since an hour-long queue wait on a scarce Vera Rubin partition is expected load behaviour; (2) ask the cluster admins to re-check the four nodes excluded in #2339 — with those back in the pool the gpu:2/128G/24cpu request has materially more candidates; (3) if the partition is genuinely oversubscribed, reserve capacity for the rubin account rather than relying on --immediate. Allocation ID 2425807 on partition vrnvl72 is the handle for an admin to confirm why it never started.

Related: #2339 (node exclusions), #2352 (2-GPU request instead of whole node), #2182 (added the nixl-ci-gpu-vr pipeline)

🛡️ This comment had 1 potential secret(s) redacted (Hex High Entropy String). See request_id 60ee6835-1049-4af0-b0ff-493591739ab0 in the triage console for the audit trail.

@aranadive
aranadive enabled auto-merge (squash) October 9, 2026 20:51
@aranadive

Copy link
Copy Markdown
Contributor

/ok to test 42fd117

@aranadive

Copy link
Copy Markdown
Contributor

/build

@aranadive
aranadive merged commit 53fece0 into ai-dynamo:main Oct 10, 2026
18 of 21 checks passed

This branch was previously deployed

1 inactive deployment
SWX_AWS — 42fd1175 Deployed Oct 9, 2026 by copy-pr-bot[bot] via Run AWS Tests #9861
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants