abi/screenshot-to-code · error · ValueError

Prompt file must contain a JSON array.

Error message

Prompt file must contain a JSON array.

What it means

ValueError("Prompt file must contain a JSON array.") raised by load_prompts() in run_image_generation_evals.py when json.loads succeeds but the top-level value is not a list (it is a dict, string, number, etc.). The eval script only accepts an array of prompt items, so any object-wrapped format like {"prompts": [...]} aborts the run before any image is generated.

Source

Thrown at backend/run_image_generation_evals.py:63

MODEL_PATHS: dict[ReplicateEvalModel, str] = {
    "flux_2_klein": FLUX_2_KLEIN_MODEL_PATH,
    "z_image_turbo": Z_IMAGE_TURBO_MODEL_PATH,
}

DEFAULT_PROMPT_FILE = Path("image_generation/eval_sets/recent_assets_20_prompts.json")
DEFAULT_OUTPUT_ROOT = Path("image_generation/eval_results")


def slugify(text: str) -> str:
    text = text.lower()
    text = re.sub(r"[^a-z0-9]+", "-", text).strip("-")
    return text[:60] or "prompt"


def load_prompts(prompt_file: Path) -> list[PromptItem]:
    raw: Any = json.loads(prompt_file.read_text())
    if not isinstance(raw, list):
        raise ValueError("Prompt file must contain a JSON array.")

    prompts: list[PromptItem] = []
    for index, item in enumerate(cast(list[Any], raw), start=1):
        if isinstance(item, str):
            prompts.append(
                {
                    "id": f"{index:03d}",
                    "category": "Prompt",
                    "prompt": item,
                }
            )
            continue

        if not isinstance(item, dict):
            raise ValueError(f"Prompt item {index} must be a string or object.")

        item_dict = cast(dict[str, Any], item)
        prompt = item_dict.get("prompt")

View on GitHub (pinned to d026163f58)

Solutions

  1. Rewrite the prompt file so the top level is an array: ["a prompt", {"id": "p1", "prompt": "...", "category": "..."}]
  2. If the wrapper is intentional, extend load_prompts to unwrap a known key such as raw["prompts"] before the isinstance check
  3. Validate the file shape before the run: python -c "import json;assert isinstance(json.load(open('prompts.json')),list)"

Example fix

// before prompts.json
{"prompts": ["a cat", "a dog"]}

// after prompts.json
["a cat", "a dog"]
Defensive patterns

Strategy: validation

Validate before calling

import json

def validate_prompt_file(path: str) -> list:
    raw = json.loads(open(path, encoding="utf-8").read())
    if not isinstance(raw, list):
        raise ValueError(f"Top level is {type(raw).__name__}, expected a JSON array")
    return raw

Type guard

from typing import Any, TypeGuard

def is_prompt_array(raw: Any) -> TypeGuard[list[Any]]:
    return isinstance(raw, list)

Try / catch

try:
    prompts = load_prompts(prompt_file)
except ValueError as e:
    if "must contain a JSON array" in str(e):
        fix_prompt_file_shape(prompt_file)  # unwrap envelope / re-export as array
    raise

Prevention

When it happens

Trigger: Running `poetry run python run_image_generation_evals.py --prompt-file prompts.json` where prompts.json is an object (e.g. {"prompts": [...], "version": 2}) or a bare JSON string/number.

Common situations: Prompt files authored by hand or exported from tools that wrap arrays in an envelope object; reusing a config-style JSON file instead of a prompt list.

Related errors


AI-assisted analysis of abi/screenshot-to-code@d026163f58 (2026-08-14). Data as JSON: /api/errors/b27c13f02cef8955. Report an issue: GitHub.