{"record":{"id":"2276c97911510073","repo":"sgl-project/sglang","slug":"model-type-must-be-specified","errorCode":null,"errorMessage":"Model type must be specified","messagePattern":"Model type must be specified","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/parser/reasoning_parser.py","lineNumber":1972,"sourceCode":"        \"mistral\": MistralDetector,\n        \"nemotron_3\": Nemotron3Detector,\n        \"interns1\": Qwen3Detector,\n        \"gemma4\": Gemma4Detector,\n        \"inkling\": InklingDetector,\n        \"cohere_command4\": CohereCommand4Detector,\n    }\n\n    def __init__(\n        self,\n        model_type: Optional[str] = None,\n        stream_reasoning: bool = True,\n        force_reasoning: Optional[bool] = None,\n        request: ChatCompletionRequest = None,\n        tokenizer=None,\n        tool_call_parser_active: bool = False,\n    ):\n        if not model_type:\n            raise ValueError(\"Model type must be specified\")\n\n        detector_class = self.DetectorMap.get(model_type.lower())\n        if not detector_class:\n            raise ValueError(f\"Unsupported model type: {model_type}\")\n\n        chat_template_kwargs = getattr(request, \"chat_template_kwargs\", None) or {}\n\n        # Special cases where we override force_reasoning\n        if model_type.lower() in {\n            \"qwen3-thinking\",\n            \"gpt-oss\",\n            \"minimax\",\n        }:\n            force_reasoning = True\n\n        # M3 consumes the <mm:think> start tag only for thinking_mode=enabled\n        # (absent from output → must force); mirror serving_chat's M3 branch.\n        if model_type.lower() == \"minimax-m3\" and force_reasoning is None:","sourceCodeStart":1954,"sourceCodeEnd":1990,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/parser/reasoning_parser.py#L1954-L1990","documentation":"ReasoningParser.__init__ requires a non-empty model_type string; it uses it to select a detector class from DetectorMap and refuses to construct with a falsy value (empty string or None).","triggerScenarios":"Constructing ReasoningParser(model_type='') or ReasoningParser(model_type=None), often because --reasoning-parser was set on the server but the per-request model type resolved empty.","commonSituations":"Server args wiring where model_type comes from a config lookup that returned None, or programmatic parser construction without a model name.","solutions":["Pass a concrete model type such as 'deepseek-r1', 'qwen3-thinking', etc.","Trace where the empty model_type originated (server args / model config) and fix that wiring","If constructing manually, default to a known parser name"],"exampleFix":"// before\nparser = ReasoningParser(model_type=model_type)  # model_type is None\n// after\nparser = ReasoningParser(model_type=model_type or \"deepseek-r1\")","handlingStrategy":"validation","validationCode":"if not model_type:\n    raise ValueError(\"model_type must be provided (check --reasoning-parser wiring)\")\nparser = ReasoningParser(model_type=model_type)","typeGuard":"def has_model_type(mt: Any) -> TypeGuard[str]:\n    return isinstance(mt, str) and bool(mt.strip())","tryCatchPattern":"try:\n    parser = ReasoningParser(model_type=model_type)\nexcept ValueError as e:\n    if \"must be specified\" in str(e):\n        fix_model_type_source()  # e.g. default from server args\n    else:\n        raise","preventionTips":["Default model_type from a known config value at startup","Fail fast on empty parser names in server-args validation","Log the resolved model_type before parser construction"],"tags":["reasoning-parser","model-type","constructor"],"backgroundTag":"missing-model-type","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}