[Rust] Gate health on startup warmup completion - #37994
Merged
alisonshao merged 1 commit intoSep 9, 2026
Merged
Conversation
nvpohanh
force-pushed
the
codex/fix-rust-openai-parity-ci
branch
from
September 4, 2026 13:36
63de001 to
4946e5a
Compare
Collaborator
Author
nvpohanh
marked this pull request as ready for review
September 4, 2026 13:59
nvpohanh
requested review from
CatherineSue,
JustinTong0323,
ispobock,
merrymercy and
slin1237
as code owners
September 4, 2026 13:59
Collaborator
Author
|
/rerun-tests test/registered/openai_server/basic/test_openai_completion_rust.py |
Contributor
|
Results for 🚀 |
rainj-me
approved these changes
Sep 4, 2026
Collaborator
Author
|
/tag-and-rerun-ci |
nvpohanh
force-pushed
the
codex/fix-rust-openai-parity-ci
branch
from
September 7, 2026 08:22
4946e5a to
3a28ccd
Compare
Collaborator
Author
|
/rerun-failed-ci |
nvpohanh
enabled auto-merge (squash)
September 8, 2026 13:10
Collaborator
Author
|
All NV pipelines have passed |
alisonshao
self-requested a review
September 9, 2026 18:51
alisonshao
approved these changes
Sep 9, 2026
alisonshao
disabled auto-merge
September 9, 2026 20:15
pllimax
added a commit
to pllimax/sglang
that referenced
this pull request
Sep 10, 2026
* origin/main: (27 commits) [Simulator] Give the OFFLINE/BLOCKING comparison tolerances real headroom (sgl-project#38732) [Config] msgspec.Struct for the config tier (sgl-project#38753) [AMD] ci: move the miles nightlies from rocm700 to rocm10 (sgl-project#37495) [Config] One writer for the declaration stash; no exception to the write seal (sgl-project#38752) docker(xpu): drop redundant setvars.sh from torch_memory_saver RUN (sgl-project#38665) [XPU][Fix] Pack device-pointer tables as uint64 to avoid 64-bit address overflow (sgl-project#35051) [CI] Temporarily disable GB300 tests (sgl-project#38770) [diffusion] feat: spill large tensors over shared memory like numpy arrays (sgl-project#38656) [diffusion] refactor: refactor utility ownership and document helper placement (sgl-project#38699) [NPU]Support GLM5.2 and FP8 DSA&Indexer kvcache for 950 (sgl-project#38250) [CI] Answer unrecognized slash commands instead of skipping silently (sgl-project#38736) [AMD] Parallelize aiter spec-decode KV index building over token blocks (sgl-project#37659) [DSv4] Integrate TRT-LLM DSv4 Attention for SM100/103 (sgl-project#30805) Add Opt-In for GLM-5.3 Flash breakable prefill CUDA graphs (sgl-project#38522) [CI] Install helion 1.4.0 for the KDA Helion kernel tests (sgl-project#38688) [Rust] Gate health on startup warmup completion (sgl-project#37994) [HiCache] Replace skip_lock_node_ids with a segment lock protocol (sgl-project#36848) feat: add optimized Domino rollout to DFlash V2 (sgl-project#36899) [CI] Add /run-full-ci and /run-extra-ci slash commands (sgl-project#38734) [Model] Support GLM-5.3 Flash NVFP4 loading (sgl-project#38621) ...
mqhc2020
pushed a commit
to mqhc2020/sglang
that referenced
this pull request
Sep 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[by Codex]
Summary
/healthand/health_generateat 503 until startup warmup has completed successfully.--skip-server-warmup: when it is explicitly set, Rust starts ready.test_openai_completion_rust.pyunchanged; radix cache and normal server warmup remain enabled.CI impact
This fixes a recurring flake in
test/registered/openai_server/basic/test_openai_completion_rust.pythat has broken pre-merge CI for many unrelated changes. I found the same failure in at least eight pre-merge runs across seven PRs: #28403, #30315, #33068, #35599, #37284, #37601 (twice), and #37820. The test compares Python and Rust frontend logprobs exactly, so the readiness race could fail an otherwise healthy PR without any relevant code changes.Error and root cause
The Python frontend keeps both health endpoints at 503 while
ServerStatusisStarting, and changes the status only after startup warmup succeeds. The Rust listener is intentionally bound before the main process runs_execute_server_warmup, because the warmup path first queries/model_info. However, the Rust health handler previously submitted its own one-token scheduler probe immediately and returned 200 when that probe made progress. Rust could therefore advertise readiness earlier than Python:popen_launch_servercould observe a healthy server and send the parity test's completion while the real eight-token startup warmup was still running.With radix cache enabled, this race changed which request populated or reused the shared prompt prefix. The Python launch commonly evaluated the completion with
#new-token: 3, #cached-token: 2/3, while the raced Rust launch evaluated the full prompt with#new-token: 5/6, #cached-token: 0, or co-batched it with warmup. The output tokens were the same, but the different forward-pass shape could produce bitwise-different logprobs on the CI GPU. Radix cache exposed the startup race; it was not the underlying bug.This behavior originated with the native Rust health handlers in #32876. The parity test was added in #33103. The earlier flake caused by default prefill CUDA graphs (#33352) was a separate issue and was fixed by #34146.
Why this works
The main process adds an internal marker header only to the startup warmup request. Rust middleware recognizes that marker only on the three actual warmup routes (
/generate,/encode, and/v1/chat/completions) and records readiness after a successful response. Both health modes check the same atomic readiness state before returning 200 or running a generation probe. Therefore Rust now follows the Python frontend'sServerStatus.Startingcontract: health remains 503 during warmup and a health success implies that startup warmup has completed.If warmup fails, readiness remains false. If warmup is explicitly skipped, the launch-time flag initializes readiness true.
Validation
test_openai_completion_rust.pypassed with normal warmup and radix cache enabled (1 passed, 421.484 s).POST /generate200, 6 new / 0 cached), then health (GET /health_generate200), then the tested completion (3 new / 2 cached), matching the Python request shape.Failure being addressed: https://github.com/sgl-project/sglang/actions/runs/33831875719/job/100902930637?pr=35599
CI States
Latest PR Test (Base): ✅ Run #34100216762
Latest PR Test (Extra): ✅ Run #34414379326
Latest PR Test (AMD ROCm 10): ❌ Run #34100215649