{"record":{"id":"cee61cb61a87f6fb","repo":"sgl-project/sglang","slug":"option-must-be-a-dict-or-a-comma-separated-compo","errorCode":null,"errorMessage":"{option} must be a dict or a comma-separated component=value string","messagePattern":"(.+?) must be a dict or a comma-separated component=value string","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/server_args/server_args.py","lineNumber":1038,"sourceCode":"        try:\n            return AttentionBackendEnum[normalized.upper()].name.lower()\n        except KeyError:\n            raise ValueError(\n                f\"Invalid attention backend '{backend}'. \"\n                f\"Available options are: {[e.name.lower() for e in AttentionBackendEnum]}\"\n            ) from None\n\n    @staticmethod\n    def _parse_component_value_map(\n        value: dict[str, Any] | str | None, *, option: str\n    ) -> dict[str, str]:\n        \"\"\"Parse a ``component=value`` map, the same shape as component backends.\"\"\"\n        if value is None or value == \"\":\n            return {}\n        if isinstance(value, dict):\n            return {str(k): str(v) for k, v in value.items()}\n        if not isinstance(value, str):\n            raise ValueError(\n                f\"{option} must be a dict or a comma-separated component=value string\"\n            )\n        try:\n            parsed = json.loads(value)\n            if isinstance(parsed, dict):\n                return {str(k): str(v) for k, v in parsed.items()}\n        except json.JSONDecodeError:\n            pass\n        result: dict[str, str] = {}\n        for pair in value.split(\",\"):\n            pair = pair.strip()\n            if not pair:\n                continue\n            if \"=\" not in pair:\n                raise ValueError(f\"{option} must use component=value entries\")\n            component, entry = pair.split(\"=\", 1)\n            result[component.strip()] = entry.strip()\n        return result","sourceCodeStart":1020,"sourceCodeEnd":1056,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/server_args/server_args.py#L1020-L1056","documentation":"_parse_component_value_map accepts None, '', a dict, or a comma-separated 'component=value' string (also JSON object strings). Any other type (int, list, bool) raises this error; option names the offending setting.","triggerScenarios":"Passing a list like ['text=8', 'vision=16'] or an int to a component-map option; JSON that parses to a non-dict (e.g. a JSON array string) falls through to the type check on the next iteration path.","commonSituations":"Building component maps programmatically and passing sequences instead of joined strings; config schemas that type the field as a list; JSON strings that contain arrays instead of objects.","solutions":["Join list values: ','.join(parts) or pass a dict {'text': '8'}","Pass a JSON object string like '{\"text\": \"8\"}' if you need JSON","Ensure the config field is typed as str or dict, not list"],"exampleFix":"# before\nargs.layerwise_tuning_for = [\"text=8\", \"vision=16\"]\n# after\nargs.layerwise_tuning_for = \"text=8,vision=16\"","handlingStrategy":"type-guard","validationCode":"if isinstance(value, (list, tuple)):\n    value = ','.join(value)\nif not isinstance(value, (str, dict)) and value not in (None, ''):\n    raise SystemExit('component map must be a dict or comma-separated string')","typeGuard":"def is_component_map(v) -> bool:\n    return v is None or v == '' or isinstance(v, (str, dict))","tryCatchPattern":null,"preventionTips":["Type config fields as str|dict in schemas (pydantic/JSON Schema)","Join lists into comma-separated strings at the config boundary"],"tags":["config-parsing","component-map","type-validation"],"backgroundTag":"wrong-argument-type","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}