{"record":{"id":"a288329ee73d3c51","repo":"sgl-project/sglang","slug":"batching-config-rule-cannot-set-both-model-and-mod","errorCode":null,"errorMessage":"batching config rule cannot set both model and model_contains","messagePattern":"batching config rule cannot set both model and model_contains","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/managers/dynamic_batch_admission.py","lineNumber":107,"sourceCode":"            raise ValueError(\"batching config rule requires max_batch_size\")\n\n        rule = cls(\n            model=_optional_str(data.get(\"model\")),\n            model_contains=_optional_str(data.get(\"model_contains\")),\n            resolution=_optional_str(data.get(\"resolution\")),\n            device_memory_gb_min=_optional_float(data.get(\"device_memory_gb_min\")),\n            device_memory_gb_max=_optional_float(data.get(\"device_memory_gb_max\")),\n            offload=_optional_bool(data.get(\"offload\")),\n            max_batch_size=int(data[\"max_batch_size\"]),\n            max_cost=_optional_float(data.get(\"max_cost\")),\n            source=source,\n        )\n        rule.validate()\n        return rule\n\n    def validate(self) -> None:\n        if self.model is not None and self.model_contains is not None:\n            raise ValueError(\n                \"batching config rule cannot set both model and model_contains\"\n            )\n        if self.model is None and self.model_contains is None:\n            raise ValueError(\"batching config rule requires model or model_contains\")\n        if self.max_batch_size < 1:\n            raise ValueError(\"batching config rule max_batch_size must be >= 1\")\n        if self.max_cost is not None and self.max_cost <= 0.0:\n            raise ValueError(\"batching config rule max_cost must be > 0\")\n        if (\n            self.device_memory_gb_min is not None\n            and self.device_memory_gb_max is not None\n            and self.device_memory_gb_min > self.device_memory_gb_max\n        ):\n            raise ValueError(\n                \"batching config rule device_memory_gb_min must be <= device_memory_gb_max\"\n            )\n\n    def matches(","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/managers/dynamic_batch_admission.py#L89-L125","documentation":"A BatchingRule cannot restrict matches by both an exact model name and a model_contains substring; the two selectors are mutually exclusive. validate() runs at the end of from_dict and raises when both fields are non-None.","triggerScenarios":"A config rule containing both \"model\" and \"model_contains\" keys, e.g. {\"model\": \"foo\", \"model_contains\": \"bar\", \"max_batch_size\": 4}.","commonSituations":"Copy-paste of an existing rule followed by adding model_contains for a broader match, leaving the old exact model key in place; schema drift after the rule format added model_contains.","solutions":["Delete either \"model\" or \"model_contains\" from the rule, keeping exactly one selector","If you need both exact and substring matches, split into two separate rules"],"exampleFix":"// before\n{\"model\": \"qwen-image\", \"model_contains\": \"qwen\", \"max_batch_size\": 4}\n// after\n{\"model_contains\": \"qwen\", \"max_batch_size\": 4}","handlingStrategy":"validation","validationCode":"for i, r in enumerate(rules):\n    if \"model\" in r and \"model_contains\" in r:\n        raise SystemExit(f\"rule[{i}]: model and model_contains are mutually exclusive\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Decide per rule whether you need exact or substring matching before writing it"],"tags":["config","batching","validation","mutually-exclusive"],"backgroundTag":"conflicting-config-options","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}