{"record":{"id":"b688b258a92601b2","repo":"sgl-project/sglang","slug":"invalid-modality-string-modality-str-valid-mod","errorCode":null,"errorMessage":"Invalid modality string: {modality_str}. Valid modalities are: {[m.name for m in Modality]}","messagePattern":"Invalid modality string: (.+?)\\. Valid modalities are: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/managers/schedule_batch.py","lineNumber":315,"sourceCode":"        return {\n            \"type\": \"abort\",\n            \"message\": self.message,\n            \"status_code\": self.status_code,\n            \"err_type\": self.err_type,\n        }\n\n\nclass Modality(Enum):\n    IMAGE = auto()\n    VIDEO = auto()\n    AUDIO = auto()\n\n    @staticmethod\n    def from_str(modality_str: str):\n        try:\n            return Modality[modality_str.upper()]\n        except KeyError:\n            raise ValueError(\n                f\"Invalid modality string: {modality_str}. Valid modalities are: {[m.name for m in Modality]}\"\n            )\n\n    @staticmethod\n    def all():\n        return [Modality.IMAGE, Modality.VIDEO, Modality.AUDIO]\n\n\nclass MultimodalInputFormat(Enum):\n    NORMAL = auto()\n    PROCESSOR_OUTPUT = auto()\n    PRECOMPUTED_EMBEDDING = auto()\n\n\n# Msgpack-native containers and Ext-decoded tensor/transport leaves. Tuple\n# containers intentionally decode as lists, matching msgpack's native model.\nMultimodalDataValue: TypeAlias = object\n","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/managers/schedule_batch.py#L297-L333","documentation":"Modality.from_str converts a modality name to the Modality enum via Modality[name.upper()]; unknown names raise ValueError listing valid options (IMAGE, VIDEO, AUDIO, and any other enum members).","triggerScenarios":"Modality.from_str('image ') (whitespace), 'img', 'text', or a typo like 'vido' — usually from parsing a user-supplied modality field in an API or config.","commonSituations":"REST/schema fields accepting free-form modality strings; frontend sending abbreviations ('img','aud').","solutions":["Send exact enum names case-insensitively: 'image', 'video', 'audio'","Strip/normalize input: from_str(s.strip().lower()) compatible spellings","Catch ValueError and return a 400 with the valid list"],"exampleFix":"# before\nmod = Modality.from_str('img')\n# after\nmod = Modality.from_str('image')","handlingStrategy":"try-catch","validationCode":"VALID = {m.name.lower() for m in Modality}\nmodality_str = modality_str.strip().lower()\nassert modality_str in VALID, f'invalid modality {modality_str}'","typeGuard":"def is_valid_modality(s): return isinstance(s, str) and s.strip().upper() in Modality.__members__","tryCatchPattern":"try:\n    mod = Modality.from_str(s)\nexcept ValueError:\n    return json_error(400, f'invalid modality: {s}; valid: image, video, audio')","preventionTips":["Normalize free-form input (strip, lower) before enum lookup","Expose the valid list in your API schema"],"tags":["sglang","modality","enum-validation"],"backgroundTag":"invalid-enum-value","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}