Skip to content

fix: make rollout /run failures recoverable - #1788

Closed
yuchenwang3 wants to merge 2 commits into
NVIDIA-NeMo:mainfrom
yuchenwang3:recoverable-rollout-errors
Closed

fix: make rollout /run failures recoverable#1788
yuchenwang3 wants to merge 2 commits into
NVIDIA-NeMo:mainfrom
yuchenwang3:recoverable-rollout-errors

Conversation

@yuchenwang3

Copy link
Copy Markdown
Contributor

Two issues that together turn one resource-server error into a fatal crash:

  1. raise_for_status re-raises aiohttp's ClientResponseError unchanged. It holds request_info/history/headers, which are multidict.CIMultiDictProxy objects that don't pickle. When rollout collection runs under Ray, the exception is pickled to cross actors and the run dies with can't pickle CIMultiDictProxy — so any resource-server 5xx takes down the whole job instead of failing a single rollout. Strip the unpicklable fields; keep status/message/response_content.

  2. _post_subroutine never retries /run. A transient 5xx (e.g. a momentarily overloaded code-exec server) aborts the batch. Retry a few times on 5xx/connection errors; leave 4xx alone.

How we hit it: under GRPO, a vLLM worker 500s on a NaN logprob (fixed separately in NVIDIA-NeMo/RL#2962). That 500 reaches raise_for_status, and (1) then crashes the whole rollout collection on the unpicklable exception rather than surfacing the underlying error.

@copy-pr-bot

copy-pr-bot Bot commented Jun 26, 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.

@nemo-automation-bot nemo-automation-bot Bot added the community-request Issue reported or requested by someone from the community label Jun 26, 2026
raise_for_status re-raises aiohttp's ClientResponseError unchanged. It carries
request_info/history/headers, which are multidict.CIMultiDictProxy objects that
don't pickle. When rollout collection runs under Ray the exception is pickled to
cross actors and the run dies with "can't pickle CIMultiDictProxy" - so any
resource-server 5xx takes down the whole job instead of failing one rollout.

Strip the unpicklable fields; keep status/message/response_content.

Signed-off-by: yuchenwang3 <yuchenwang3@users.noreply.github.com>
_post_subroutine doesn't retry /run, so a transient 5xx (e.g. a momentarily
overloaded code-exec server) aborts the batch. Retry a few times on 5xx and
connection errors; leave 4xx alone.

Signed-off-by: yuchenwang3 <yuchenwang3@users.noreply.github.com>
@yuchenwang3 yuchenwang3 changed the title Make rollout /run failures recoverable fix: make rollout /run failures recoverable Jun 26, 2026
@yuchenwang3
yuchenwang3 force-pushed the recoverable-rollout-errors branch from 03e29e7 to 22ed1af Compare June 26, 2026 22:09
@svcnvidia-nemo-ci svcnvidia-nemo-ci added the waiting-on-maintainers Waiting on maintainers to respond label Jun 29, 2026
@yuchenwang3

Copy link
Copy Markdown
Contributor Author

Ping — waiting on CI authorization since Jun 26. Could a maintainer /ok to test and review? This makes rollout /run failures recoverable instead of fatal, which matters for long RL runs where a single transient env error currently kills the job.

@svcnvidia-nemo-ci svcnvidia-nemo-ci added waiting-on-maintainers Waiting on maintainers to respond and removed waiting-on-maintainers Waiting on maintainers to respond labels Jul 10, 2026
@yuchenwang3

Copy link
Copy Markdown
Contributor Author

@marta-sd sorry for the direct ping — you've been the main recent committer on rollout_collection.py, so you seemed like the right reviewer. This makes rollout /run failures recoverable instead of fatal — right now a single transient env error kills a long RL run. Waiting on the copy-pr-bot gate since Jun 26 — could you /ok to test and take a look?

@svcnvidia-nemo-ci svcnvidia-nemo-ci added waiting-on-maintainers Waiting on maintainers to respond and removed waiting-on-maintainers Waiting on maintainers to respond labels Jul 15, 2026
@github-actions github-actions Bot added the sla:triage-overdue Review assignment is over the one-business-day SLA label Jul 17, 2026
ritaneves added a commit that referenced this pull request Jul 17, 2026
## Summary

- Grant the PR SLA tracker pull-requests: write.
- Update the workflow permission regression test.

## Root cause

The first tracker run received 403 Resource not accessible by
integration while adding an SLA label to PR #1788. The workflow granted
only pull-requests: read, so it exited before creating or updating the
tracker issue.

## Impact

The workflow can now reconcile SLA labels on pull requests and continue
to create or update [Tracker] Pull request handoff SLA.

## Validation

- .venv/bin/pytest -q tests/unit_tests/test_pr_sla_tracker.py
- 24 passed

Failed run:
https://github.com/NVIDIA-NeMo/Gym/actions/runs/29570272742/job/87852135838

Signed-off-by: Rita Fernandes Neves <rfernandesne@nvidia.com>
@yuchenwang3

Copy link
Copy Markdown
Contributor Author

@kajalj22 pinging you as the most active recent merger in this repo — earlier pings didn't find an owner. This makes rollout /run failures recoverable instead of fatal: unpicklable ClientResponseError crossing Ray actors currently kills long RL runs on a single resource-server hiccup. It's been waiting on the copy-pr-bot gate since Jun 26. Could you /ok to test and review, or route it to the right owner?

@svcnvidia-nemo-ci svcnvidia-nemo-ci removed the waiting-on-maintainers Waiting on maintainers to respond label Aug 6, 2026
OlegSudakov pushed a commit to OlegSudakov/Gym that referenced this pull request Aug 7, 2026
## Summary

- Grant the PR SLA tracker pull-requests: write.
- Update the workflow permission regression test.

## Root cause

The first tracker run received 403 Resource not accessible by
integration while adding an SLA label to PR NVIDIA-NeMo#1788. The workflow granted
only pull-requests: read, so it exited before creating or updating the
tracker issue.

## Impact

The workflow can now reconcile SLA labels on pull requests and continue
to create or update [Tracker] Pull request handoff SLA.

## Validation

- .venv/bin/pytest -q tests/unit_tests/test_pr_sla_tracker.py
- 24 passed

Failed run:
https://github.com/NVIDIA-NeMo/Gym/actions/runs/29570272742/job/87852135838

Signed-off-by: Rita Fernandes Neves <rfernandesne@nvidia.com>
@svcnvidia-nemo-ci svcnvidia-nemo-ci added the waiting-on-maintainers Waiting on maintainers to respond label Aug 8, 2026
@marta-sd

Copy link
Copy Markdown
Contributor

cc @ritaneves for finding a reviewer

@svcnvidia-nemo-ci svcnvidia-nemo-ci removed the waiting-on-maintainers Waiting on maintainers to respond label Aug 10, 2026
@bxyu-nvidia

Copy link
Copy Markdown
Contributor

Hi @yuchenwang3! For these automatic retries, I think this would just end up with truly failing benchmarks retry longer and fail slower. Typically for these retries we will leave them for the individual servers to handle rather than have a global retry mechnism which may be suboptimal/unintuitive for some scenarios

@svcnvidia-nemo-ci svcnvidia-nemo-ci added the waiting-on-customer Waiting on the original author to respond label Aug 11, 2026
@yuchenwang3

Copy link
Copy Markdown
Contributor Author

Fair point on the retry — that half I'm happy to cut. I'd just want to keep the other half from getting thrown out with it, since the bug that actually kills runs has nothing to do with retry policy: raise_for_status re-raises aiohttp's ClientResponseError with request_info/history/headers still attached, and those are CIMultiDictProxy objects that don't pickle. So the first resource-server 5xx that crosses a Ray actor boundary takes down the entire rollout collection with can't pickle CIMultiDictProxy instead of failing that one rollout — you never even see the underlying error. That's how we hit it: a vLLM worker 500'd on a NaN logprob and the GRPO run died on the pickle error rather than surfacing the 500.

On retries themselves, agreed the individual server is the right owner — a global loop can't know which benchmarks are idempotent or how fast a truly-failing one should give up. So how about I drop the retry loop in _post_subroutine and this PR becomes just the exception-hygiene fix in server_utils.py (strip the unpicklable fields, keep status/message/response_content)? Failures still fail fast, they just propagate as the real error instead of a pickle crash. If that works I'll update the PR.

@ananthsub ananthsub left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exception handling change to avoid unpickleable exception content looks good to me. If we can make this PR just that addition without the extra retry loop changes, it's good to merge

Comment thread nemo_gym/server_utils.py
Comment on lines +235 to +243
# request_info/history/headers are multidict.CIMultiDictProxy objects
# that don't pickle, which breaks Ray's cross-actor error propagation
# (rollout collection dies with "can't pickle CIMultiDictProxy" on any
# resource-server 5xx). Drop them so the error stays picklable; keep
# status/message/response_content.
e.request_info = None
e.history = ()
e.headers = None
e.args = (e.status, e.message)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yuchenwang3 this change looks good to me. Let's start with getting this merged without the retry-loop addition

@github-actions github-actions Bot removed the sla:triage-overdue Review assignment is over the one-business-day SLA label Aug 24, 2026
@yuchenwang3

Copy link
Copy Markdown
Contributor Author

Thanks — #2726 takes the exception-serialization fix forward without the retry loop, with stronger spawn-process coverage, and keeps the co-author credit. Closing this one as superseded.

@svcnvidia-nemo-ci svcnvidia-nemo-ci removed the waiting-on-customer Waiting on the original author to respond label Aug 25, 2026
ananthsub added a commit to ananthsub/Gym that referenced this pull request Aug 25, 2026
Replace aiohttp's unpicklable response metadata with plain values while preserving the status, message, URL, headers, and response body. Based on the exception-handling fix proposed by Yuchen Wang in NVIDIA-NeMo#1788.

Co-authored-by: Yuchen Wang <yuchenwang3@users.noreply.github.com>
Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
ananthsub added a commit to ananthsub/Gym that referenced this pull request Aug 25, 2026
Replace aiohttp's unpicklable response metadata with plain values while preserving the status, message, URL, headers, and response body. Based on the exception-handling fix proposed by Yuchen Wang in NVIDIA-NeMo#1788.

Co-authored-by: Yuchen Wang <yuchenwang3@users.noreply.github.com>
Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
ananthsub added a commit to ananthsub/Gym that referenced this pull request Aug 25, 2026
Replace aiohttp's unpicklable response metadata with plain values while preserving the status, message, URL, headers, and response body. Based on the exception-handling fix proposed by Yuchen Wang in NVIDIA-NeMo#1788.

Co-authored-by: Yuchen Wang <yuchenwang3@users.noreply.github.com>
Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
ananthsub added a commit to ananthsub/Gym that referenced this pull request Aug 26, 2026
Replace aiohttp's unpicklable response metadata with pickle-safe values while preserving the status, message, URL, case-insensitive multi-value headers, and response body. Based on the exception-handling fix proposed by Yuchen Wang in NVIDIA-NeMo#1788.

Co-authored-by: Yuchen Wang <yuchenwang3@users.noreply.github.com>
Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
ananthsub added a commit to ananthsub/Gym that referenced this pull request Aug 26, 2026
Replace aiohttp's unpicklable response metadata with pickle-safe values while preserving the status, message, URL, case-insensitive multi-value headers, and response body. Based on the exception-handling fix proposed by Yuchen Wang in NVIDIA-NeMo#1788.

Co-authored-by: Yuchen Wang <yuchenwang3@users.noreply.github.com>
Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
ananthsub added a commit to ananthsub/Gym that referenced this pull request Aug 26, 2026
Replace aiohttp's unpicklable response metadata with pickle-safe values while preserving the status, message, URL, case-insensitive multi-value headers, and response body. Based on the exception-handling fix proposed by Yuchen Wang in NVIDIA-NeMo#1788.

Co-authored-by: Yuchen Wang <yuchenwang3@users.noreply.github.com>
Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
ananthsub added a commit that referenced this pull request Aug 26, 2026
## Summary
- replace unpicklable `aiohttp.ClientResponseError` proxy metadata with
pickle-safe values before propagation
- preserve HTTP status, message, URL, case-insensitive multi-value
request and response headers, and response body
- verify the exception and header semantics survive a spawned-process
round trip

This extracts and hardens the exception-handling fix proposed by
@yuchenwang3 in #1788. The original PR also changes rollout retries;
this PR intentionally contains only the serialization fix.

Co-authored-by: Yuchen Wang <yuchenwang3@users.noreply.github.com>

## Test plan
- [x] `uv run --extra dev pre-commit run --files
nemo_gym/server_utils.py tests/unit_tests/test_server_utils.py`
- [x] `uv run --extra dev pytest tests/unit_tests/test_server_utils.py
-q`

Signed-off-by: Ananth Subramaniam <ansubramania@nvidia.com>
Co-authored-by: Yuchen Wang <yuchenwang3@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-request Issue reported or requested by someone from the community

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants