vllm-project/vllm · error · ValueError

{models_url} did not return a model list.

Error message

{models_url} did not return a model list.

What it means

During Recipes API discovery, the tool fetches {api_base}/models.json and expects a JSON array of model objects. If the response is anything else (an error object, an HTML error page parsed as JSON, a schema change), it raises ValueError naming the URL that misbehaved.

Source

Thrown at tools/recipes/recipe_json_to_vllm_config.py:338

            return f"{strategy} (recommended)"
        return strategy

    selected = choose_from_menu(strategies, strategy_label, "Select strategy: ")
    return selected, sources[selected]


def discover_recipe_source(
    api_base: str,
    requested_model: str | None,
    requested_hardware: str | None,
    requested_strategy: str | None,
) -> str:
    print("No recipe JSON supplied; starting Recipes API discovery.")

    models_url = api_url(api_base, "/models.json")
    models_data = load_json(models_url)
    if not isinstance(models_data, list):
        raise ValueError(f"{models_url} did not return a model list.")

    models = [model for model in models_data if isinstance(model, dict)]
    model = select_model(models, requested_model)

    model_json_path = model.get("json")
    if not isinstance(model_json_path, str) or not model_json_path:
        raise ValueError(f"Selected model {model.get('hf_id')!r} has no JSON API path.")

    model_json_url = api_url(api_base, model_json_path)
    model_data = load_json(model_json_url)
    if not isinstance(model_data, dict):
        raise ValueError(f"{model_json_url} did not return a JSON object.")

    recommended = model_data.get("recommended_command")
    if not isinstance(recommended, dict):
        raise ValueError(
            f"Model {model.get('hf_id')!r} has no rendered "
            "recommended_command in the Recipes API."

View on GitHub (pinned to c794754062)

Solutions

  1. Check the URL from the message in a browser/curl: `curl -sL <models_url> | head -c 300` and confirm it returns a JSON array.
  2. If the API is temporarily broken, retry later or pin a known-good api base.
  3. Bypass discovery entirely by passing a recipe JSON URL/file directly.

Example fix

# before
python tools/recipes/recipe_json_to_vllm_config.py
# -> ValueError: https://recipes.vllm.ai/models.json did not return a model list.

# after
curl -sL https://recipes.vllm.ai/models.json | head -c 200   # verify array output
python tools/recipes/recipe_json_to_vllm_config.py https://recipes.vllm.ai/<model>/<hw>/<recipe>.json
Defensive patterns

Strategy: retry

Validate before calling

import json, urllib.request
data = json.load(urllib.request.urlopen(models_url, timeout=30))
if not isinstance(data, list):
    raise SystemExit(f"{models_url} returned {type(data).__name__}, expected a list; API unhealthy or wrong --api-base")

Type guard

def is_model_list(data: object) -> bool:
    return isinstance(data, list) and all(isinstance(m, dict) for m in data)

Try / catch

for attempt in range(3):
    try:
        data = load_json(models_url)
        break
    except (urllib.error.URLError, json.JSONDecodeError) as e:
        if attempt == 2:
            raise SystemExit(f"Recipes API unreachable: {e}; pass a recipe JSON file instead") from e

Prevention

When it happens

Trigger: The Recipes API (default https://recipes.vllm.ai) returning a JSON object/error payload instead of a list at /models.json; a custom --api-base that serves a different schema; a proxy or captive portal returning HTML that json.load() happens to accept as a dict.

Common situations: Recipes API outage or format migration; pointing --api-base at an internal mirror that does not implement /models.json; network middleboxes intercepting the request.

Related errors


AI-assisted analysis of vllm-project/vllm@c794754062 (2026-08-14). Data as JSON: /api/errors/cd70bac89930d56a. Report an issue: GitHub.