{"record":{"id":"4541bb2972aebf65","repo":"mudler/LocalAI","slug":"engine-args-must-be-a-json-object-got-type-extra","errorCode":null,"errorMessage":"engine_args must be a JSON object, got {type(extra).__name__}","messagePattern":"engine_args must be a JSON object, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/python/sglang/backend.py","lineNumber":127,"sourceCode":"        \"\"\"Merge user-supplied engine_args (JSON object) into the kwargs dict\n        that will be forwarded to ``sglang.Engine`` (which constructs a\n        ``ServerArgs`` from them).\n\n        Mirrors ``backend/python/vllm/backend.py::_apply_engine_args`` but\n        operates on the kwargs dict because sglang's ``Engine.__init__``\n        accepts ``**kwargs`` directly rather than a pre-built dataclass.\n        Validation happens against ``ServerArgs`` fields so a typo fails\n        early with a close-match suggestion instead of producing a confusing\n        ``TypeError`` deep inside engine startup.\n        \"\"\"\n        if not engine_args_json:\n            return engine_kwargs\n        try:\n            extra = json.loads(engine_args_json)\n        except json.JSONDecodeError as e:\n            raise ValueError(f\"engine_args is not valid JSON: {e}\") from e\n        if not isinstance(extra, dict):\n            raise ValueError(\n                f\"engine_args must be a JSON object, got {type(extra).__name__}\"\n            )\n        valid = {f.name for f in dataclasses.fields(ServerArgs)}\n        for key in extra:\n            if key not in valid:\n                suggestion = difflib.get_close_matches(key, valid, n=1)\n                hint = f\" did you mean {suggestion[0]!r}?\" if suggestion else \"\"\n                raise ValueError(f\"unknown engine_args key {key!r}.{hint}\")\n        engine_kwargs.update(extra)\n        return engine_kwargs\n\n    def _messages_to_dicts(self, messages) -> List[dict]:\n        result: List[dict] = []\n        for msg in messages:\n            d = {\"role\": msg.role, \"content\": msg.content or \"\"}\n            if msg.name:\n                d[\"name\"] = msg.name\n            if msg.tool_call_id:","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/backend/python/sglang/backend.py#L109-L145","documentation":"Raised by the sglang backend's engine-args parser when the engine_args JSON parses successfully but is not an object — e.g. a JSON array, string, number, or boolean. Only a dict can be merged into the engine kwargs, so any other top-level JSON type is rejected with the offending type name in the message.","triggerScenarios":"engine_args set to '[\"--tp-size\", \"2\"]' (array of CLI-style flags) or '\"tp_size=2\"' (a plain JSON string) instead of an object.","commonSituations":"Users porting CLI-style argument lists from sglang/vllm command lines into engine_args, or wrapping the whole thing in quotes so it parses as a JSON string.","solutions":["Use a JSON object with ServerArgs field names as keys: '{\"tp_size\": 2}'","Convert CLI flags to object form (--tp-size 2 -> \"tp_size\": 2)","Drop outer quotes that turn the object into a string"],"exampleFix":"# before\nengine_args: '[\"--tp-size\", \"2\"]'\n\n# after\nengine_args: '{\"tp_size\": 2}'","handlingStrategy":"type-guard","validationCode":"import json\nextra = json.loads(cfg['engine_args'])\nif not isinstance(extra, dict):\n    raise ValueError(f'engine_args must be a JSON object, got {type(extra).__name__}')","typeGuard":"def is_engine_args_object(s: str) -> bool:\n    try:\n        return isinstance(json.loads(s), dict)\n    except (TypeError, json.JSONDecodeError):\n        return False","tryCatchPattern":"try:\n    kwargs = _apply_engine_args(base, engine_args_json)\nexcept ValueError as err:\n    fail_config(str(err))","preventionTips":["Convert CLI flag lists to {key: value} object form","Do not wrap the whole object in extra quotes","Mirror the documented example format exactly"],"tags":["python","sglang","json","configuration"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}