odysseus-dev/odysseus · error · ValueError
invalid JSON in {path}: {exc.msg} at line {exc.lineno}, colu
Error message
invalid JSON in {path}: {exc.msg} at line {exc.lineno}, column {exc.colno} What it means
Raised by load_json_file in scripts/pr_blocker_audit.py when a JSON file passed as an offline input (PR snapshot, cache, or config) fails to parse with json.load. The original json.JSONDecodeError message, line, and column are embedded, and the exception is re-raised as ValueError so callers only need to handle one exception type for bad input files.
Source
Thrown at scripts/pr_blocker_audit.py:159
def finish_line(self) -> None:
if self.enabled and self.last_len:
self.stream.write(f"\r{' ' * self.last_len}\r")
self.stream.flush()
self.last_len = 0
def summary(self, message: str) -> None:
if self.enabled:
self.finish_line()
self.stream.write(f"{message}\n")
self.stream.flush()
def load_json_file(path: Path):
try:
with path.open("r", encoding="utf-8") as handle:
return json.load(handle)
except json.JSONDecodeError as exc:
raise ValueError(f"invalid JSON in {path}: {exc.msg} at line {exc.lineno}, column {exc.colno}") from exc
except OSError as exc:
raise ValueError(f"could not read {path}: {exc}") from exc
def fetch_live_prs(repo: str, fetch_files: bool = True, progress: ProgressReporter | None = None, limit: int = 1000):
progress = progress or ProgressReporter(False)
fields = (
"number,title,author,files,mergeStateStatus,reviewDecision,updatedAt,url"
if fetch_files
else "number,title,author,mergeStateStatus,reviewDecision,updatedAt,url"
)
cmd = ["gh", "pr", "list", "--repo", repo, "--state", "open", "--limit", str(limit), "--json", fields]
progress.phase("Fetching open PR list...")
try:
payload = _run_gh_json(cmd)
except RuntimeError:
api_path = f"repos/{repo}/pulls?state=open&per_page=100"
payload = _run_gh_json(["gh", "api", "--paginate", api_path])View on GitHub (pinned to f9235ebbf1)
Solutions
- Open the file at the reported line/column and fix the JSON syntax error (the message gives the exact position).
- Validate with an external tool first: python -m json.tool <file> or jq . <file> to get a second opinion on the error location.
- If the file is JSONL or a gh --paginate capture, wrap it into a single array before passing it (e.g. jq -s . < in > out).
- Re-capture the file from its source (gh pr list --json ...) instead of hand-editing.
Example fix
# before $ python scripts/pr_blocker_audit.py --input prs.json ValueError: invalid JSON in prs.json: Expecting ',' delimiter at line 12, column 5 # after $ python -m json.tool prs.json # locate/fix line 12 $ python scripts/pr_blocker_audit.py --input prs.json
Defensive patterns
Strategy: validation
Validate before calling
import json
from pathlib import Path
def validate_json_input(path: str | Path) -> dict | list:
p = Path(path)
data = json.loads(p.read_text(encoding='utf-8-sig')) # tolerate BOM
return data Type guard
def is_valid_json_file(path: str) -> bool:
try:
with open(path, 'r', encoding='utf-8-sig') as fh:
json.load(fh)
return True
except (json.JSONDecodeError, OSError):
return False Try / catch
try:
payload = load_json_file(Path(args.input))
except ValueError as e:
if 'invalid JSON in' in str(e):
print(f'Fix the JSON syntax error: {e}', file=sys.stderr)
raise SystemExit(2) Prevention
- Generate input snapshots programmatically (gh pr list --json ... > file) instead of hand-editing.
- Validate files with jq or python -m json.tool before passing them to the audit script.
- Read with utf-8-sig in your own tooling to survive editor-added BOMs.
- Keep one JSON document per file; wrap JSONL with jq -s . first.
When it happens
Trigger: Running pr_blocker_audit.py with --input <file> (or any flag that loads a JSON snapshot) where the file has a syntax error: trailing comma, unescaped newline in a string, BOM, truncated download, or JSONL content fed where a single JSON document is expected.
Common situations: Hand-editing a gh pr list --json dump and breaking syntax; a partially-written/interrupted file capture; piping JSONL (one object per line) into an argument that expects one array; Windows BOM prepended by an editor.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- expected input JSON to be a list of pull requests or an obje
- could not read {path}: {exc}
- gh returned invalid JSON: {exc}
- Invalid JSON
- Expected a JSON object
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/60117f9f8d4b91af.
Report an issue: GitHub.