Skip to content

fix(speculative): fail closed when the streaming /done check cannot be reached - #2756

Open
h-guo18 wants to merge 1 commit into
mainfrom
haoguo/streaming-done-fail-closed
Open

h-guo18 wants to merge 1 commit into
mainfrom
haoguo/streaming-done-fail-closed

Conversation

@h-guo18

@h-guo18 h-guo18 commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Type of change: Bug fix

EagleVllmStreamingDataset (the RDMA streaming path) reads a sample's hidden states, then asks the vLLM sidecar's /done whether the slot's ring lapped the read. When that call failed, the read was assumed valid, so a sidecar outage could feed overwritten hidden states into training without a warning.

  • A failed /done now discards the read as a miss: it warns, resamples, and counts against the existing consecutive-failure circuit breaker (fail_after_consecutive_skips).
  • Only transport failures count as a miss, per the module's _TRANSIENT_FETCH_ERRORS (httpx.HTTPError, OSError); raise_for_status() makes a non-2xx answer one of them. A 200 without valid is a sidecar contract break and raises, like the other contract violations in _fetch.

Usage

No API change.

Testing

tests/unit/torch/speculative/plugins/test_hf_streaming_dataset.py: 21 passed. New tests:

  • a transport error on the first /done resamples and returns the next sample;
  • a 503 is a miss even when its body says valid: true;
  • a 200 without valid raises KeyError. This one fails if the except is widened back to Exception.

Before your PR is "Ready for review"

  • Is this change backward compatible?: ✅
  • If you copied code from any other sources or added a new PIP dependency, did you follow guidance in CONTRIBUTING.md: N/A
  • Did you write any new necessary tests?: ✅
  • Did you update Changelog?: N/A
  • Did you get Claude approval on this PR?: N/A

Additional Information

Split out of #2279, which is about training speed.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Completion checks now correctly distinguish successful responses from failed requests, preventing incomplete or failed checks from being treated as valid.
    • Transient connection errors now trigger a resample instead of allowing the current read to proceed.
    • Successful responses missing required validity information now surface an error rather than silently passing.

…e reached

EagleVllmStreamingDataset reads a sample's hidden states over RDMA, then asks the vLLM
sidecar's /done whether the slot's ring lapped the read (stale bytes). When that call
failed, the read was assumed valid, so a sidecar outage could feed overwritten hidden
states into training without a warning. A failed /done cannot prove the bytes are the
sample's, and a resample is cheap, so the read is now discarded as a miss: it warns and
counts against the existing consecutive-failure circuit breaker.

Only transport failures count as a miss, per the module's own _TRANSIENT_FETCH_ERRORS
(httpx.HTTPError, OSError), with raise_for_status() so a non-2xx answer is one too. A 200
without `valid` breaks the sidecar contract and raises, as other contract violations in
_fetch do, rather than turning every sample into a miss until the breaker blames the server.

Split out of #2279.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: h-guo18 <67671475+h-guo18@users.noreply.github.com>
@h-guo18
h-guo18 requested review from a team as code owners October 12, 2026 07:23
@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: NVIDIA/Model-Optimizer/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: 1c5bef65-9804-43d0-848a-86c2a7ba6c31

📥 Commits

Reviewing files that changed from the base of the PR and between f27b476 and 1c18c7e.


📒 Files selected for processing (2)
  • modelopt/torch/speculative/plugins/hf_streaming_dataset.py
  • tests/unit/torch/speculative/plugins/test_hf_streaming_dataset.py

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



📝 Walkthrough

Walkthrough

EagleVllmStreamingDataset._fetch now checks the /done response status. It returns None for transient fetch errors so the dataset can resample, and propagates other exceptions. Tests cover transport errors, non-2xx responses, and a successful response without valid.

Changes

/done response handling

Layer / File(s) Summary
Fetch handling and validation
modelopt/torch/speculative/plugins/hf_streaming_dataset.py, tests/unit/torch/speculative/plugins/test_hf_streaming_dataset.py
_fetch checks the /done response status and returns None after transient fetch errors. Tests cover resampling after a transport error, a 503 response despite a valid: True body, and a 200 response missing valid.

Priority: ⬇️ Low

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

Change: Bug fix

Suggested reviewers: kevalmorabia97


Merge Risk: ⚪ Minimal · up to 1c18c

No identified issue currently blocks merging; run the normal checks before merging.

Pre-merge checks | Passed 5 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 72.73% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: fail-closed handling when the streaming /done check is unreachable.
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.
Security Anti-Patterns Passed PASS. The pull request changes only /done error handling and adds tests. The added Python lines contain no torch.load(..., weights_only=False), numpy.load(..., allow_pickle=True), hardcoded `tru…

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR


🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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

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

h-guo18 added a commit that referenced this pull request Oct 12, 2026
Failing closed on an unreachable /done is a correctness fix unrelated to training speed, so
it gets its own PR, #2756, which also narrows the except to the module's transient errors.
This restores hf_streaming_dataset.py and its test to main's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: h-guo18 <67671475+h-guo18@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://NVIDIA.github.io/Model-Optimizer/pr-preview/pr-2756/

Built to branch gh-pages at 2026-10-12 07:28 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@codecov

codecov Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.26%. Comparing base (f27b476) to head (1c18c7e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2756      +/-   ##
==========================================
+ Coverage   69.47%   78.26%   +8.78%     
==========================================
  Files         646      646              
  Lines       71672    71675       +3     
==========================================
+ Hits        49796    56093    +6297     
+ Misses      21876    15582    -6294     
Flag Coverage Δ
examples-diffusers 20.29% <0.00%> (-0.01%) ⬇️
examples-gpt-oss 13.54% <0.00%> (-0.01%) ⬇️
examples-hf_ptq 23.38% <0.00%> (-0.04%) ⬇️
examples-llm_distill 13.62% <0.00%> (-0.01%) ⬇️
examples-llm_eval 17.33% <0.00%> (-0.01%) ⬇️
examples-llm_qat 17.63% <0.00%> (-0.01%) ⬇️
examples-llm_sparsity 15.87% <0.00%> (-0.01%) ⬇️
examples-megatron_bridge 26.70% <0.00%> (-0.15%) ⬇️
examples-specdec_bench 13.31% <0.00%> (-0.01%) ⬇️
examples-speculative_decoding 17.62% <0.00%> (-0.07%) ⬇️
examples-torch_onnx 21.67% <0.00%> (-0.01%) ⬇️
examples-torch_trt 15.31% <0.00%> (-0.01%) ⬇️
examples-vllm_serve 13.99% <0.00%> (-0.01%) ⬇️
gpu 59.15% <0.00%> (+37.42%) ⬆️
regression 15.16% <0.00%> (-0.01%) ⬇️
unit 59.89% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant