usestrix/strix · error · RuntimeError
vulnerabilities.json at
Error message
vulnerabilities.json at {path} is not a list What it means
After successfully parsing vulnerabilities.json, ReportState requires the top-level JSON value to be a list (the file is an array of vulnerability report objects). Any other JSON type (object, string, number) raises RuntimeError. This guards the hydration contract before indexing saved report ids.
Solutions
- Rewrite vulnerabilities.json as a JSON array of report objects: [ {...}, {...} ].
- If an object with a key like 'vulnerabilities' was written, extract that array into the file root.
- If uncertain of the expected shape, generate a fresh run and compare its vulnerabilities.json structure.
- Delete the run dir if the run is disposable.
Example fix
// before: vulnerabilities.json
{"vulnerabilities": [{"id": "VULN-001"}]}
// after: vulnerabilities.json
[{"id": "VULN-001"}] Defensive patterns
Strategy: type-guard
Validate before calling
import json
from pathlib import Path
def vuln_json_is_list(run_dir: Path) -> bool:
p = run_dir / "vulnerabilities.json"
if not p.exists():
return True
try:
return isinstance(json.loads(p.read_text(encoding="utf-8")), list)
except (OSError, json.JSONDecodeError):
return False Type guard
def is_vuln_file_shape(data: object) -> bool:
return isinstance(data, list) and all(isinstance(r, dict) for r in data) Try / catch
try:
state = ReportState(run_dir)
except RuntimeError as exc:
if "is not a list" in str(exc):
# repair shape: extract array from wrapper object, then retry
... Prevention
- Keep vulnerabilities.json an array of objects; never wrap it in a keyed object.
- Validate external tooling that writes into run dirs against a fresh scan's file shape.
- Add a JSON-schema check in CI when artifacts are archived.
When it happens
Trigger: vulnerabilities.json parses as valid JSON but is not an array — e.g. someone hand-edited it into an object like {"vulnerabilities": [...]}, or a different tool wrote an object-shaped file into the run dir.
Common situations: Manual editing or scripting over the run artifacts; schema drift after upgrading Strix; merging outputs from another reporting tool into the same run dir.
Related errors
- vulnerabilities.json at
- run.json at is not an object
- run.json at is unreadable
- Agent ' ' cannot be stopped while
- Agent coordinator is unavailable
AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15).
Data as JSON: /api/errors/048ba2cfc2046026.
Report an issue: GitHub.
Appendix: source
Thrown at strix/report/state.py:204
scan_results = data.get("scan_results")
if isinstance(scan_results, dict):
self.scan_results = scan_results
self.final_scan_result = self._format_final_scan_result(scan_results)
self._hydrate_llm_usage(data.get("llm_usage"))
logger.info("report state hydrated run.json from %s", run_dir)
json_path = run_dir / "vulnerabilities.json"
if json_path.exists():
try:
data = json.loads(json_path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
raise RuntimeError(
f"vulnerabilities.json at {json_path} is corrupt ({exc}); "
f"refusing to start fresh — that would overwrite prior "
f"vulnerability MDs on disk. Inspect or delete the run dir.",
) from exc
if not isinstance(data, list):
raise RuntimeError(
f"vulnerabilities.json at {json_path} is not a list",
)
self.vulnerability_reports = [r for r in data if isinstance(r, dict)]
for r in self.vulnerability_reports:
rid = r.get("id")
if isinstance(rid, str):
self._saved_vuln_ids.add(rid)
logger.info(
"report state hydrated %d vulnerability report(s)",
len(self.vulnerability_reports),
)
def add_vulnerability_report(
self,
title: str,
severity: str,
description: str | None = None,
impact: str | None = None,View on GitHub (pinned to 8551339130)