[Bugfix][Structured Outputs] Reject empty `structural_tag` at request validation (#47450)
Signed-off-by: linnea-lin-00638949 <15521435947@163.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Artem Perevedentsev <aperevedents@nvidia.com>
linyafeng committed
Sep 22, 2026 at 21:09 UTC
e548298f8144cae77d26949078c264d819d3993c
2 files changed
+19
-2
tests/v1/structured_output/test_validation.py
+7
-2
@@ -56,13 +56,18 @@ def test_plain_request_allowed_for_diffusion_models():
56
[
57
(StructuredOutputsParams(json_object=False), "json_object must be True"),
58
(StructuredOutputsParams(json=""), "json cannot be an empty string"),
59
+ (
60
+ StructuredOutputsParams(structural_tag=""),
61
+ "structural_tag cannot be an empty string",
62
+ ),
63
],
64
)
65
def test_degenerate_structured_outputs_rejected(structured_outputs, match):
66
"""json_object=False and an empty json schema pass the `is not None`
67
exclusivity check but resolve to no structured-output key, so they must be
64
- rejected at request validation (-> 400) instead of reaching and crashing
65
- the engine."""
68
+ rejected at request validation (-> 400). Empty `structural_tag` is rejected
69
+ for the same reason: `json.loads("")` in `compile_grammar` would otherwise
70
+ raise JSONDecodeError and surface as a per-request engine error."""
71
params = SamplingParams(structured_outputs=structured_outputs)
72
with pytest.raises(VLLMValidationError, match=match):
73
params._validate_structured_outputs(
vllm/sampling_params.py
+12
@@ -1144,6 +1144,18 @@ class SamplingParams(
1144
raise VLLMValidationError(
1145
"structured_outputs.regex must not contain a NUL character ('\\x00')"
1146
)
1147
+ # Note(arpera):
1148
+ # We do NOT check here structured output regex on emptiness because
1149
+ # empty regex is indeed compiles to a valid grammar as well as
1150
+ # whitespace-only regexps, for instance, regex="\n" or regex=" "
1151
+ # are valid patterns and we MUST process them.
1152
+ if (
1153
+ isinstance(self.structured_outputs.structural_tag, str)
1154
+ and self.structured_outputs.structural_tag.strip() == ""
1155
+ ):
1156
+ raise VLLMValidationError(
1157
+ "structured_outputs.structural_tag cannot be an empty string"
1158
+ )
1159
1160
from vllm.v1.structured_output.backend_guidance import (
1161
has_guidance_unsupported_json_features,