{"record":{"id":"fea33f8446d69fdf","repo":"mudler/LocalAI","slug":"unknown-engine-args-key-key-r-hint-fea33f","errorCode":null,"errorMessage":"unknown engine_args key {key!r}.{hint}","messagePattern":"unknown engine_args key (.+?)\\.(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/python/vllm/backend.py","lineNumber":146,"sourceCode":"\n        Unknown keys raise ValueError with the closest valid field as a hint.\n        \"\"\"\n        if not engine_args_json:\n            return engine_args\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(type(engine_args))}\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        return dataclasses.replace(engine_args, **extra)\n\n    def _messages_to_dicts(self, messages):\n        \"\"\"Convert proto Messages to list of dicts suitable for apply_chat_template().\"\"\"\n        result = []\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:\n                d[\"tool_call_id\"] = msg.tool_call_id\n            if msg.reasoning_content:\n                d[\"reasoning_content\"] = msg.reasoning_content\n            if msg.tool_calls:\n                try:\n                    tool_calls = json.loads(msg.tool_calls)\n                except json.JSONDecodeError:\n                    pass","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/backend/python/vllm/backend.py#L128-L164","documentation":"Raised by _apply_engine_args when a key in the model YAML's engine_args JSON object does not match any field of the vllm AsyncEngineArgs dataclass (checked via dataclasses.fields). The backend uses difflib.get_close_matches to add a 'did you mean X?' hint for near-misses, so typos are usually self-diagnosing.","triggerScenarios":"engine_args containing keys like \"trustremotecode\" (missing underscores), \"tensor_parallel\" instead of tensor_parallel_size, or keys that only exist in a different vLLM version's EngineArgs. Any key not in the field set of the installed vLLM's AsyncEngineArgs raises with the suggestion hint.","commonSituations":"Version skew: an option valid in newer vLLM (e.g. enable_prefix_caching shapes changed across releases) used against an older pinned vLLM; typo'd field names; copying engine_args from a vLLM CLI example that uses CLI flags (dashes) instead of dataclass field names (underscores).","solutions":["Read the hint in the error — if present, rename the key to the suggested field name","Convert CLI-style flags to dataclass names: --tensor-parallel-size becomes tensor_parallel_size","Check the installed vLLM version's AsyncEngineArgs fields (python -c \"import dataclasses,vllm.engine.arg_utils as a; print([f.name for f in dataclasses.fields(a.AsyncEngineArgs)])\") and keep only keys present there","Upgrade/align the vLLM version in backend/python/vllm/requirements so the field exists"],"exampleFix":"# before\nengine_args: '{\"trustremotecode\": true}'\n# after\nengine_args: '{\"trust_remote_code\": true}'","handlingStrategy":"validation","validationCode":"import dataclasses, json\nfrom vllm.engine.arg_utils import AsyncEngineArgs\nvalid = {f.name for f in dataclasses.fields(AsyncEngineArgs)}\nextras = json.loads(model_config['engine_args'])\nbad = [k for k in extras if k not in valid]","typeGuard":"def unknown_engine_args_keys(engine_args_json: str) -> list[str]:\n    valid = {f.name for f in dataclasses.fields(AsyncEngineArgs)}\n    try:\n        extras = json.loads(engine_args_json)\n    except json.JSONDecodeError:\n        return []\n    return [k for k in extras if not isinstance(extras, dict) or k not in valid]","tryCatchPattern":"try:\n    backend.load(request)\nexcept ValueError as e:\n    if 'unknown engine_args key' in str(e):\n        # error already carries a 'did you mean' hint; act on it\n        apply_hint_and_retry(str(e))\n    else:\n        raise","preventionTips":["Generate the valid key set from the installed vLLM's AsyncEngineArgs and validate configs against it in CI","Convert vLLM CLI flag names to underscore field names before writing them into engine_args","Pin the vLLM version so the field set is stable"],"tags":["vllm","config","typo","version-skew","backend"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}