{"record":{"id":"b6e74e4ac9de4137","repo":"vllm-project/vllm","slug":"recipe-json-must-be-a-json-object","errorCode":null,"errorMessage":"Recipe JSON must be a JSON object.","messagePattern":"Recipe JSON must be a JSON object\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/recipes/recipe_json_to_vllm_config.py","lineNumber":641,"sourceCode":"\ndef main() -> int:\n    args = parse_args()\n\n    try:\n        source = args.source\n        if source is None:\n            source = discover_recipe_source(\n                args.api_base, args.model, args.hardware, args.strategy\n            )\n        elif args.model or args.hardware or args.strategy:\n            raise ValueError(\n                \"Do not combine a positional recipe JSON source with \"\n                \"--model/--hardware/--strategy discovery options.\"\n            )\n\n        recipe = load_json(source)\n        if not isinstance(recipe, dict):\n            raise ValueError(\"Recipe JSON must be a JSON object.\")\n\n        argv = recipe_argv(recipe)\n        config = argv_to_config(argv)\n        write_config(args.config_out, source, recipe, config)\n        write_env(args.env_out, source, recipe)\n    except Exception as exc:\n        print(f\"ERROR: {exc}\", file=sys.stderr)\n        return 1\n\n    print(f\"Wrote {args.config_out}\")\n    print(f\"Wrote {args.env_out}\")\n    print()\n    print(\"Run:\")\n    print(f\"  source {shlex.quote(args.env_out)}\")\n    print(f\"  vllm serve --config {shlex.quote(args.config_out)}\")\n    return 0\n\n","sourceCodeStart":623,"sourceCodeEnd":659,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/tools/recipes/recipe_json_to_vllm_config.py#L623-L659","documentation":"In main(), after load_json(source) succeeds, the top-level recipe must be a JSON object (dict). If the source file/URL contains a JSON list, string, number, or null, there is no recipe structure to read deploy_type/argv/env from, so the tool fails immediately.","triggerScenarios":"Passing a URL/path whose JSON is an array — e.g. pointing the tool at models.json (a list) instead of a per-hardware recipe object; passing a .json that contains a bare string; a truncated file that parses to null.","commonSituations":"Confusing the API's model list endpoint with a recipe endpoint; test fixtures with wrong top-level type; API returning a JSON array of recipes for a listing path.","solutions":["Check the source's top-level type: jq -r 'type' recipe.json (must report 'object')","If it is a list of recipes, pick the right element and save just that object as the file","Make sure you passed the per-hardware recipe JSON URL/file, not models.json or a listing endpoint"],"exampleFix":"# before\npython tools/recipes/recipe_json_to_vllm_config.py https://recipes.vllm.ai/models.json\n# after\npython tools/recipes/recipe_json_to_vllm_config.py https://recipes.vllm.ai/recipes/org/model/h100.json","handlingStrategy":"validation","validationCode":"recipe = json.loads(Path(source).read_text())\nif not isinstance(recipe, dict):\n    raise SystemExit(f\"top-level JSON is {type(recipe).__name__}, must be object\")","typeGuard":"def is_json_object(x: object) -> bool:\n    return isinstance(x, dict)","tryCatchPattern":null,"preventionTips":["jq -r 'type' your source file before invoking the tool","Keep saved recipe files per-hardware and object-shaped; do not store arrays of recipes as converter input"],"tags":["vllm-recipes","json-shape","input-validation"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}