nexu-io/open-design · error · SystemExit

review does not contain row-level results

Error message

review does not contain row-level results

What it means

Raised by rows_to_repair() in queue_pet_repairs.py when review.get('rows') is not a list. The repair loop depends on row-level QA results (each row carrying state/errors/warnings), so a review payload without a rows array is treated as a schema mismatch, not an empty repair set.

Source

Thrown at skills/hatch-pet/scripts/queue_pet_repairs.py:24

import argparse
import json
import shutil
from datetime import datetime, timezone
from pathlib import Path


def load_json(path: Path) -> dict[str, object]:
    if not path.exists():
        raise SystemExit(f"file not found: {path}")
    return json.loads(path.read_text(encoding="utf-8"))


def rows_to_repair(
    review: dict[str, object], *, repair_on_warnings: bool
) -> list[dict[str, object]]:
    rows = review.get("rows")
    if not isinstance(rows, list):
        raise SystemExit("review does not contain row-level results")

    repairs: list[dict[str, object]] = []
    for row in rows:
        if not isinstance(row, dict) or not isinstance(row.get("state"), str):
            continue
        errors = row.get("errors") if isinstance(row.get("errors"), list) else []
        warnings = row.get("warnings") if isinstance(row.get("warnings"), list) else []
        if errors or (repair_on_warnings and warnings):
            repairs.append(
                {
                    "state": row["state"],
                    "reason": "; ".join(str(item) for item in [*errors, *warnings])
                    or "the row did not pass visual QA",
                }
            )
    return repairs

View on GitHub (pinned to 5be4028344)

Solutions

  1. Re-run the QA review so it emits a top-level rows: [...] array with per-row state/errors/warnings.
  2. Inspect the review file: jq '.rows | type' review.json should report 'array'.
  3. Confirm --review points at the row-level review artifact, not the manifest.
  4. If the schema genuinely changed, transform the file into {"rows": [...]} before retrying.

Example fix

# before: review.json = {"overall": "fail"}
# after: review.json = {"rows": [{"state": "idle", "errors": ["empty slot"]}]}
Defensive patterns

Strategy: type-guard

Validate before calling

rows = review.get("rows")
if not isinstance(rows, list):
    raise SystemExit("review.json must have a top-level 'rows' array; got " + type(rows).__name__)

Type guard

def is_row_review(payload: object) -> bool:
    return isinstance(payload, dict) and isinstance(payload.get("rows"), list)

Prevention

When it happens

Trigger: Feeding a whole-run summary JSON (no per-row breakdown) as --review; the QA reviewer wrote a different top-level key (e.g. 'results' or 'frames'); the file is valid JSON but the wrong artifact entirely.

Common situations: QA pipeline changed its output schema between runs; reviewer emitted slide-level instead of row-level verdicts; user pointed --review at imagegen-jobs.json by mistake.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/0fc84b4f4cea248c. Report an issue: GitHub.