usestrix/strix · error · RuntimeError

run.json at {path} is unreadable: {exc}

Error message

run.json at {path} is unreadable: {exc}

What it means

read_run_record() loads strix_runs/<run>/run.json to resume or report on a run. If the file exists but raises OSError or json.JSONDecodeError on read/parse, it raises RuntimeError with the underlying cause chained. Missing files are fine (returns {}); only unreadable/corrupt files fail.

Source

Thrown at strix/report/writer.py:103

    """Return a markdown fence tag for ``code``, defaulting to ``python`` when
    auto-detection is inconclusive."""
    try:
        lexer = guess_lexer(code)
    except ClassNotFound:
        return "python"
    if isinstance(lexer, TextLexer) or not lexer.aliases:
        return "python"
    return str(lexer.aliases[0])


def read_run_record(run_dir: Path) -> dict[str, Any]:
    path = run_record_path(run_dir)
    if not path.exists():
        return {}
    try:
        data = json.loads(path.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError) as exc:
        raise RuntimeError(f"run.json at {path} is unreadable: {exc}") from exc
    if not isinstance(data, dict):
        raise TypeError(f"run.json at {path} is not an object")
    return data


def write_run_record(run_dir: Path, run_record: dict[str, Any]) -> None:
    _atomic_write_text(
        run_record_path(run_dir),
        json.dumps(run_record, ensure_ascii=False, indent=2, default=str),
    )


def write_executive_report(run_dir: Path, final_scan_result: str) -> None:
    path = run_dir / "penetration_test_report.md"
    with path.open("w", encoding="utf-8") as f:
        f.write("# Security Penetration Test Report\n\n")
        f.write(f"**Generated:** {datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S UTC')}\n\n")
        f.write(f"{final_scan_result}\n")

View on GitHub (pinned to 8551339130)

Solutions

  1. Validate the file manually: python -m json.tool strix_runs/<run>/run.json to see the parse error.
  2. Restore or regenerate run.json if the run is still recoverable; otherwise delete the run dir.
  3. Fix permissions (chown/chmod) if OSError was the cause.
  4. Free disk space and re-run the scan to produce a clean record.
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

def run_json_readable(run_dir: Path) -> bool:
    p = run_dir / "run.json"
    if not p.exists():
        return True
    try:
        json.loads(p.read_text(encoding="utf-8"))
        return True
    except (OSError, json.JSONDecodeError):
        return False

Try / catch

from strix.report.writer import read_run_record
try:
    record = read_run_record(run_dir)
except RuntimeError as exc:  # unreadable/corrupt
    record = {}  # only if a missing record is acceptable for your flow
    log.warning("skipping corrupt run record: %s", exc)

Prevention

When it happens

Trigger: Any consumer of read_run_record (run status checks, cost accounting vs budget, report generation) over a run dir where run.json is truncated JSON or unreadable due to permissions. Distinct from a missing file, which is not an error.

Common situations: run.json half-written after a kill -9 or power loss (if a non-atomic write path was used); read-only or root-owned file left by a container run; file truncated by a full disk.

Related errors


AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15). Data as JSON: /api/errors/7919ffb42ffb3ff0. Report an issue: GitHub.