From 557244f34ccade5a90e1014533704100719e4db3 Mon Sep 17 00:00:00 2001 From: Shaun Walsh Date: Fri, 26 Jun 2026 11:42:55 +0100 Subject: [PATCH 1/2] [BugFix] Add field constraints to /v1/omni/sleep and /v1/omni/wakeup requests Reject empty stage_ids lists (min_length=1) and negative sleep levels (ge=0) at the entrypoint level. Unskip sleep_empty_stage_ids, sleep_negative_level, and wakeup_empty_stage_ids tests. Partial fix for #3649. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Shaun Walsh --- .../invalid_param_test/test_invalid_server_control.py | 9 ++------- vllm_omni/entrypoints/openai/api_server.py | 6 +++--- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/tests/dfx/reliability/invalid_param_test/test_invalid_server_control.py b/tests/dfx/reliability/invalid_param_test/test_invalid_server_control.py index 0a8240c4b6f..ff878492f42 100644 --- a/tests/dfx/reliability/invalid_param_test/test_invalid_server_control.py +++ b/tests/dfx/reliability/invalid_param_test/test_invalid_server_control.py @@ -13,8 +13,6 @@ pytestmark = [pytest.mark.slow, pytest.mark.diffusion, pytest.mark.omni] -_SKIP_ISSUE_3649 = pytest.mark.skip(reason="https://github.com/vllm-project/vllm-omni/issues/3649") - _QWEN_IMAGE = [ pytest.param( OmniServerParams(model="Qwen/Qwen-Image"), @@ -36,9 +34,8 @@ pytest.param( "sleep", {"stage_ids": [], "level": 2}, - ("stage_ids", "Field required", "Missing"), + ("stage_ids", "too_short", "at least 1"), id="sleep_empty_stage_ids", - marks=_SKIP_ISSUE_3649, ), pytest.param( "sleep", @@ -57,7 +54,6 @@ {"stage_ids": [0], "level": -1}, ("level", "greater"), id="sleep_negative_level", - marks=_SKIP_ISSUE_3649, ), pytest.param("wakeup", {}, ("stage_ids", "missing", "Field required"), id="wakeup_missing_stage_ids"), pytest.param( @@ -69,9 +65,8 @@ pytest.param( "wakeup", {"stage_ids": []}, - ("stage_ids", "length"), + ("stage_ids", "too_short", "at least 1"), id="wakeup_empty_stage_ids", - marks=_SKIP_ISSUE_3649, ), ], ) diff --git a/vllm_omni/entrypoints/openai/api_server.py b/vllm_omni/entrypoints/openai/api_server.py index 2c6a3d87a98..e774b166369 100755 --- a/vllm_omni/entrypoints/openai/api_server.py +++ b/vllm_omni/entrypoints/openai/api_server.py @@ -3385,12 +3385,12 @@ async def stop_profile(raw_request: Request, request: ProfileRequest | None = No class OmniSleepRequest(BaseModel): - stage_ids: list[int] - level: int = 2 + stage_ids: list[int] = Field(..., min_length=1) + level: int = Field(default=2, ge=0) class OmniWakeupRequest(BaseModel): - stage_ids: list[int] + stage_ids: list[int] = Field(..., min_length=1) @router.post("/v1/omni/sleep") From ae717f3cfbe9cd062ab6a17cd4d7f782327e87fc Mon Sep 17 00:00:00 2001 From: Shaun Walsh Date: Mon, 29 Jun 2026 16:34:44 +0100 Subject: [PATCH 2/2] Fix empty stage_ids tests to expect 422 after min_length=1 validation The min_length=1 constraint on stage_ids rejects empty lists at the Pydantic layer (422) before the handler runs. Update tests to match. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Shaun Walsh --- .../openai_api/test_omni_sleep_wakeup.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/tests/entrypoints/openai_api/test_omni_sleep_wakeup.py b/tests/entrypoints/openai_api/test_omni_sleep_wakeup.py index cf7d6e234ec..f110d2ddbfc 100644 --- a/tests/entrypoints/openai_api/test_omni_sleep_wakeup.py +++ b/tests/entrypoints/openai_api/test_omni_sleep_wakeup.py @@ -68,20 +68,15 @@ def test_sleep_default_level(sleep_capable_engine): sleep_capable_engine.sleep.assert_awaited_once_with(stage_ids=[0], level=2) -def test_sleep_empty_stage_ids(sleep_capable_engine, mocker): - """Empty stage_ids: engine is still called and returns SUCCESS with no acks.""" - sleep_capable_engine.sleep = mocker.AsyncMock(return_value=[]) +def test_sleep_empty_stage_ids(sleep_capable_engine): + """Empty stage_ids is rejected by min_length=1 validation.""" app = _make_app(sleep_capable_engine) client = TestClient(app) response = client.post("/v1/omni/sleep", json={"stage_ids": [], "level": 2}) - assert response.status_code == 200 - data = response.json() - assert data["status"] == "SUCCESS" - assert data["acks"] == [] - assert app.state.sleeping_stages == set() - sleep_capable_engine.sleep.assert_awaited_once_with(stage_ids=[], level=2) + assert response.status_code == 422 + sleep_capable_engine.sleep.assert_not_awaited() def test_sleep_updates_sleeping_set(sleep_capable_engine): @@ -152,15 +147,14 @@ def test_wakeup_partial_sleeping(sleep_capable_engine): def test_wakeup_empty_stage_ids(sleep_capable_engine): - """Empty stage_ids: any() on empty iterable is False → SKIPPED, engine not called.""" + """Empty stage_ids is rejected by min_length=1 validation.""" app = _make_app(sleep_capable_engine) app.state.sleeping_stages = {0, 1} client = TestClient(app) response = client.post("/v1/omni/wakeup", json={"stage_ids": []}) - assert response.status_code == 200 - assert response.json()["status"] == "SKIPPED" + assert response.status_code == 422 sleep_capable_engine.wake_up.assert_not_awaited()