From 8438709e9cf48e0ebce18e91cc50d57ffb7cb150 Mon Sep 17 00:00:00 2001 From: ziang663 <119752791+ziang663@users.noreply.github.com> Date: Thu, 14 May 2026 06:30:49 +0800 Subject: [PATCH] Fix scheduler admission for near-full KV requests (#25126) --- python/sglang/srt/managers/scheduler.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/python/sglang/srt/managers/scheduler.py b/python/sglang/srt/managers/scheduler.py index 21de52244..10df1914a 100644 --- a/python/sglang/srt/managers/scheduler.py +++ b/python/sglang/srt/managers/scheduler.py @@ -1865,13 +1865,24 @@ class Scheduler( self.external_corpus_manager.check_pending_load() def init_req_max_new_tokens(self, req): - req.sampling_params.max_new_tokens = min( - ( - req.sampling_params.max_new_tokens - if req.sampling_params.max_new_tokens is not None - else 1 << 30 + input_len = len(req.origin_input_ids) + # Keep this bound consistent with PrefillAdder's admission budget: + # ceil_page(input_len) + max_new_tokens + page_size must be strictly + # smaller than max_total_num_tokens. Otherwise a request can be accepted + # into the waiting queue but can never be scheduled, blocking the queue + # and eventually making health checks fail. + paged_input_len = -(-input_len // self.page_size) * self.page_size + req.sampling_params.max_new_tokens = max( + 0, + min( + ( + req.sampling_params.max_new_tokens + if req.sampling_params.max_new_tokens is not None + else 1 << 30 + ), + self.max_req_len - input_len - 1, + self.max_total_num_tokens - paged_input_len - self.page_size - 1, ), - self.max_req_len - len(req.origin_input_ids) - 1, ) def _process_and_broadcast_mm_inputs(