{"record":{"id":"4ee3820f63259d7b","repo":"unslothai/unsloth","slug":"llama-server-does-not-read-an-attached-value-writ","errorCode":null,"errorMessage":"llama-server does not read an attached value: write '{flag}' and '{value[:32]}' as two separate arguments, not '{token[:64]}'","messagePattern":"llama-server does not read an attached value: write '(.+?)' and '(.+?)' as two separate arguments, not '(.+?)'","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/llama_server_args.py","lineNumber":315,"sourceCode":"            # naming a flag that looks correct in the log. Only flag-shaped tokens:\n            # a VALUE may legitimately end in whitespace, a chat template or a\n            # grammar being the obvious ones.\n            raise ValueError(\n                f\"llama-server does not accept the spaces around '{token[:64]}': \"\n                f\"write it as '{flag}'\"\n            )\n        elif \"=\" in token:\n            # llama.cpp looks the WHOLE token up in its option map, folding only the\n            # underscore spelling, so \"--top-k=20\" is not \"--top-k\" with a value: it\n            # is an argument it has never heard of. Measured on b10342 and b10360,\n            # where --top-k=20, --ctx-size=4096 and --flash-attn=on each exit with\n            # \"error: invalid argument\". Accepting the GNU spelling here meant the\n            # switch tore down the resident model and the child then refused to\n            # start, so it is refused while it is still a 400 with somewhere to go.\n            # Splitting it here would be a guess: for a switch the value is not one,\n            # and this module cannot know an ordinary flag's arity.\n            value = token.partition(\"=\")[2]\n            raise ValueError(\n                f\"llama-server does not read an attached value: write '{flag}' and \"\n                f\"'{value[:32]}' as two separate arguments, not '{token[:64]}'\"\n            )\n        else:\n            # Its own value when attached, otherwise the tokens that follow.\n            attached = _value_is_attached(token, flag)\n            if pending_two_value > 0:\n                raise ValueError(f\"llama-server flag '{two_value_flag}' takes two values\")\n            # An attached value is ONE of the two, not the whole option:\n            # \"--control-vector-layer-range=1\" still owes its END, and\n            # llama-server exits on the incomplete option.\n            if flag in _TWO_VALUE_FLAGS:\n                pending_values = 1 if attached else 2\n                pending_two_value = pending_values\n            elif flag in _OPTIONAL_SECOND_VALUE_FLAGS:\n                # Allowed, not owed: pending_two_value stays 0, so nothing here\n                # insists on the second token.\n                pending_values = 1 if attached else 2","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/llama_server_args.py#L297-L333","documentation":"ValueError from llama_server_args.py:315 — a flag token uses GNU '--flag=value' spelling. llama.cpp looks the WHOLE token up in its option map (folding only underscores), so '--top-k=20' is an argument it has never heard of, not --top-k with a value: measured on b10342/b10360, --top-k=20, --ctx-size=4096 and --flash-attn=on each exit 'invalid argument'. Accepting it meant the model switch tore down the resident model and the child then refused to start, so it is refused while it is still a 400. The module will not split it for you because for switches the 'value' is not one, and it cannot know an ordinary flag's arity.","triggerScenarios":"Passing any '--flag=value' token in extra args: --ctx-size=4096, --top-k=20, --flash-attn=on, --split-mode=row. Every attached-value spelling of a known flag hits this branch.","commonSituations":"Muscle memory from GNU tools; copy-pasting from llama.cpp docs or blog posts that use '='; config generators emitting key=value style.","solutions":["Rewrite as two tokens: '--ctx-size 4096' instead of '--ctx-size=4096' (the error message names the exact split).","If building args programmatically from a dict, emit flag and value as separate list elements.","Grep your stored config for '=' inside tokens starting with '-' and split them at load time — except _TWO_VALUE_FLAGS and _OPTIONAL_SECOND_VALUE_FLAGS where attached handling differs, letting the validator sort it out is safer."],"exampleFix":"# before\nextra_args = [\"--ctx-size=4096\", \"--flash-attn=on\"]\n\n# after\nextra_args = [\"--ctx-size\", \"4096\", \"--flash-attn\", \"on\"]","handlingStrategy":"validation","validationCode":"extra_args = [\n    part\n    for tok in raw_args\n    for part in ((tok.split('=', 1) if tok.startswith('--') and '=' in tok else [tok]))\n]","typeGuard":"def no_attached_values(tokens) -> bool:\n    return not any(t.startswith('-') and '=' in t for t in tokens)","tryCatchPattern":"try:\n    validate_extra_args(args)\nexcept ValueError as e:\n    if \"attached value\" in str(e):\n        raise HTTPException(400, \"write flags and values as separate tokens\")\n    raise","preventionTips":["Default to space-separated flag/value pairs; llama.cpp does not parse '--flag=value'.","Emit args from a dict as alternating [flag, value] elements.","Lint stored configs for tokens matching ^--.*=.","Remember this validator refuses rather than splits — do the split yourself."],"tags":["llama-server","validation","gnu-syntax","argv","flag-parsing"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}