abi/screenshot-to-code · error · HTTPException
Invalid run id
Error message
Invalid run id
What it means
Thrown by _fetch_run() in the agent-runs router when the run_id path parameter does not match RUN_ID_PATTERN (backend/fs_logging/agent_runs.py:52: ^run_\d{8}_\d{6}_[0-9a-f]{8}$, e.g. run_20260814_153000_ab12cd34). It is a 400 FastAPI HTTPException raised before any database or filesystem access, so the run was never looked up. The strict pattern exists because run_id is joined into filesystem paths, so it doubles as path-traversal protection.
Source
Thrown at backend/routes/agent_runs.py:137
data = dict(zip(_RUN_COLUMNS, row))
data["has_unpriced_calls"] = bool(data["has_unpriced_calls"])
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()View on GitHub (pinned to d026163f58)
Solutions
- Fetch ids from GET /agent-runs and pass run.run_id verbatim instead of constructing or editing ids by hand.
- Verify the id against the regex ^run_\d{8}_\d{6}_[0-9a-f]{8}$ before issuing the request.
- Check for whitespace or URL-encoding damage (e.g. %20, unencoded underscores) in the id you are sending.
- If you maintain a producer of run ids, ensure it formats them as run_ + date + time + 8 lowercase hex chars.
Example fix
# before
resp = client.get(f"/agent-runs/{run_id}") # run_id = 'run-2026-08-14' -> 400
# after
import re
RUN_ID_RE = re.compile(r"^run_\d{8}_\d{6}_[0-9a-f]{8}$")
if not RUN_ID_RE.match(run_id):
raise ValueError(f"malformed run id: {run_id!r}
resp = client.get(f"/agent-runs/{run_id}") Defensive patterns
Strategy: validation
Validate before calling
import re
RUN_ID_RE = re.compile(r"^run_\d{8}_\d{6}_[0-9a-f]{8}$")
def is_valid_run_id(run_id: str) -> bool:
return bool(RUN_ID_RE.match(run_id))
# before the call
if not is_valid_run_id(run_id):
raise ValueError(f"malformed run id: {run_id!r}") Type guard
def is_valid_run_id(run_id: str) -> bool:
"""True when run_id matches run_YYYYMMDD_HHMMSS_xxxxxxxx (8 lowercase hex)."""
return bool(re.match(r"^run_\d{8}_\d{6}_[0-9a-f]{8}$", run_id)) Try / catch
try:
resp = client.get(f"/agent-runs/{run_id}")
except httpx.HTTPStatusError as e:
if e.response.status_code == 400 and "Invalid run id" in e.response.text:
raise ValueError(f"bad run id format: {run_id!r}") from e
raise Prevention
- Always source run ids from GET /agent-runs responses, never construct them by hand.
- Validate against the run_ pattern before making detail requests.
- Strip whitespace from ids parsed out of logs or the DOM.
When it happens
Trigger: Any GET /agent-runs/{run_id}, /agent-runs/{run_id}/output, or /agent-runs/{run_id}/assets/{filename} call where run_id lacks the run_YYYYMMDD_HHMMMM_8hexchars shape: truncated ids, ids copied with a missing segment, URL-decoded ids with stray slashes, or entirely fabricated ids.
Common situations: Frontend passes a stale or hand-edited run id; a caller reconstructs the id from a timestamp instead of reading it from the list endpoint; the id is copy-pasted with whitespace; a script iterates directory names that do not follow the run_ naming convention.
Related errors
- Invalid asset path
- max_age_days must be >= 1
- Invalid eval set name: {set_name!r}
- Invalid report filename
- Design system name is required
AI-assisted analysis of abi/screenshot-to-code@d026163f58 (2026-08-14).
Data as JSON: /api/errors/bb01c4c604622c62.
Report an issue: GitHub.