abi/screenshot-to-code · warning · HTTPException

No runs recorded

Error message

No runs recorded

What it means

Raised by _fetch_run() (404) when the SQLite index database returned by get_agent_runs_db_path() does not exist on disk. It means the backend has never recorded any agent run on this machine — the index DB is created lazily on the first run, not at startup. Note the sibling list endpoint GET /agent-runs returns an empty list in the same situation, so the detail endpoints are stricter than the list endpoint.

Solutions

  1. Run one agent generation first so the indexer creates the DB, then retry.
  2. Confirm the runs directory/db path the backend uses (call GET /agent-runs and read runs_directory from the response) and check the DB file exists there.
  3. If the DB was deleted but run directories still exist, re-run whatever indexing/recording step your version provides, or restore the DB from backup.
  4. If you moved the data directory via env var, restart the backend so paths resolve consistently.

Example fix

# before
resp = client.get(f"/agent-runs/{run_id}/output")  # 404 'No runs recorded'

# after
listing = client.get("/agent-runs").json()
if not listing["runs"]:
    print(f"no runs yet under {listing['runs_directory']}; run a generation first")
else:
    resp = client.get(f"/agent-runs/{run_id}/output")
Defensive patterns

Strategy: fallback

Validate before calling

listing = client.get("/agent-runs").json()
if not listing["runs"]:
    # index DB absent; detail calls will 404 with 'No runs recorded'
    raise SystemExit("no runs recorded yet — run a generation first")

Type guard

def has_recorded_runs(listing: dict) -> bool:
    """True when the agent-runs index exists and holds at least one run."""
    return bool(listing.get("runs"))

Try / catch

try:
    detail = client.get(f"/agent-runs/{run_id}").raise_for_status().json()
except httpx.HTTPStatusError as e:
    if e.response.status_code == 404 and "No runs recorded" in e.response.text:
        detail = None  # fresh install: nothing recorded yet
    else:
        raise

Prevention

When it happens

Trigger: Calling GET /agent-runs/{run_id} (or /output, /assets/...) on a fresh installation, or after the runs data directory was pruned/deleted, or when SCREENSHOT_TO_CODE_DATA_DIR (or the equivalent env var controlling the runs directory) points somewhere the DB was never created.

Common situations: Fresh clone/first launch before any generation run; the ~/.screenshot-to-code data dir was wiped; a changed data-dir env var between runs; pruning removed the DB file itself.

Related errors


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

Appendix: source

Thrown at backend/routes/agent_runs.py:139

    return AgentRunSummary(**data)


def _directory_size_bytes(path: str) -> int:
    total = 0
    for root, _, files in os.walk(path):
        for name in files:
            try:
                total += os.path.getsize(os.path.join(root, name))
            except OSError:
                continue
    return total


def _fetch_run(run_id: str) -> AgentRunSummary:
    if not RUN_ID_PATTERN.match(run_id):
        raise HTTPException(status_code=400, detail="Invalid run id")
    if not os.path.isfile(get_agent_runs_db_path()):
        raise HTTPException(status_code=404, detail="No runs recorded")
    conn = open_index_db()
    try:
        row = conn.execute(
            f"SELECT {', '.join(_RUN_COLUMNS)} FROM runs WHERE run_id = ?",
            (run_id,),
        ).fetchone()
    finally:
        conn.close()
    if row is None:
        raise HTTPException(status_code=404, detail="Run not found")
    return _row_to_summary(row)


@router.get("/agent-runs", response_model=AgentRunListResponse)
async def list_agent_runs(limit: int = 200) -> AgentRunListResponse:
    runs_directory = get_agent_runs_directory()
    if not os.path.isfile(get_agent_runs_db_path()):
        return AgentRunListResponse(

View on GitHub (pinned to d026163f58)