{"record":{"id":"20e4a0a6bc55684a","repo":"vllm-project/vllm","slug":"recipe-env-must-be-an-object-got-type-env-n","errorCode":null,"errorMessage":"Recipe `env` must be an object, got {type(env).__name__}","messagePattern":"Recipe `env` must be an object, got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/recipes/recipe_json_to_vllm_config.py","lineNumber":604,"sourceCode":"        f\"# Source: {source}\",\n    ]\n    for key in (\"hardware\", \"strategy\", \"variant\", \"deploy_type\"):\n        if recipe.get(key) is not None:\n            metadata.append(f\"# {key}: {recipe[key]}\")\n\n    body = yaml.safe_dump(\n        config,\n        sort_keys=False,\n        default_flow_style=False,\n        allow_unicode=True,\n    )\n    Path(path).write_text(\"\\n\".join(metadata) + \"\\n\" + body, encoding=\"utf-8\")\n\n\ndef write_env(path: str, source: str, recipe: dict[str, Any]) -> None:\n    env = recipe.get(\"env\") or {}\n    if not isinstance(env, dict):\n        raise ValueError(f\"Recipe `env` must be an object, got {type(env).__name__}\")\n\n    lines = [\n        \"#!/usr/bin/env bash\",\n        \"# Generated from vLLM Recipes JSON.\",\n        f\"# Source: {source}\",\n        \"\",\n    ]\n\n    if env:\n        for key, value in env.items():\n            lines.append(f\"export {key}={shlex.quote(str(value))}\")\n    else:\n        lines.append(\"# No recipe-specific environment variables.\")\n\n    lines.append(\"\")\n    Path(path).write_text(\"\\n\".join(lines), encoding=\"utf-8\")\n    Path(path).chmod(Path(path).stat().st_mode | 0o111)\n","sourceCodeStart":586,"sourceCodeEnd":622,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/tools/recipes/recipe_json_to_vllm_config.py#L586-L622","documentation":"write_env() generates an env.sh from the recipe's 'env' field (defaulting to {} when absent/null). If 'env' exists but is not a JSON object — e.g. a list of \"K=V\" strings or a plain string — the tool cannot iterate it as a mapping and raises this error before writing env.sh.","triggerScenarios":"Recipe JSON where env is rendered as [\"VLLM_USE_V1=1\"] (array of assignments) or \"VLLM_USE_V1=1\" (string) instead of {\"VLLM_USE_V1\": \"1\"}; schema drift in how the Recipes API serializes environment variables.","commonSituations":"Third-party recipe files adopting a different env convention; API version change; hand-written env blocks copied from systemd/Docker files (KEY=VALUE lines).","solutions":["jq '.env' recipe.json to see the actual shape","Convert the env to an object: an array of K=V strings becomes {\"K\":\"V\",...}; a single string becomes a one-key object","If the API changed its env serialization format, update the vllm checkout"],"exampleFix":"# before\n\"env\": [\"VLLM_USE_V1=1\", \"HF_TOKEN=abc\"]\n# after\n\"env\": {\"VLLM_USE_V1\": \"1\", \"HF_TOKEN\": \"abc\"}","handlingStrategy":"type-guard","validationCode":"env = recipe.get(\"env\") or {}\nif not isinstance(env, dict):\n    raise SystemExit(f\"env must be object, got {type(env).__name__}\")","typeGuard":"def is_env_object(recipe: dict) -> bool:\n    env = recipe.get(\"env\")\n    return env is None or isinstance(env, dict)","tryCatchPattern":null,"preventionTips":["Serialize env as a JSON object mapping key to value, never K=V arrays","Validate third-party recipe files against the documented schema before running the tool"],"tags":["vllm-recipes","env","schema-validation"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}