{"record":{"id":"c4c75f05572ff241","repo":"odysseus-dev/odysseus","slug":"could-not-read-path-exc","errorCode":null,"errorMessage":"could not read {path}: {exc}","messagePattern":"could not read (.+?): (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scripts/pr_blocker_audit.py","lineNumber":161,"sourceCode":"            self.stream.write(f\"\\r{' ' * self.last_len}\\r\")\n            self.stream.flush()\n            self.last_len = 0\n\n    def summary(self, message: str) -> None:\n        if self.enabled:\n            self.finish_line()\n            self.stream.write(f\"{message}\\n\")\n            self.stream.flush()\n\n\ndef load_json_file(path: Path):\n    try:\n        with path.open(\"r\", encoding=\"utf-8\") as handle:\n            return json.load(handle)\n    except json.JSONDecodeError as exc:\n        raise ValueError(f\"invalid JSON in {path}: {exc.msg} at line {exc.lineno}, column {exc.colno}\") from exc\n    except OSError as exc:\n        raise ValueError(f\"could not read {path}: {exc}\") from exc\n\n\ndef fetch_live_prs(repo: str, fetch_files: bool = True, progress: ProgressReporter | None = None, limit: int = 1000):\n    progress = progress or ProgressReporter(False)\n    fields = (\n        \"number,title,author,files,mergeStateStatus,reviewDecision,updatedAt,url\"\n        if fetch_files\n        else \"number,title,author,mergeStateStatus,reviewDecision,updatedAt,url\"\n    )\n    cmd = [\"gh\", \"pr\", \"list\", \"--repo\", repo, \"--state\", \"open\", \"--limit\", str(limit), \"--json\", fields]\n    progress.phase(\"Fetching open PR list...\")\n    try:\n        payload = _run_gh_json(cmd)\n    except RuntimeError:\n        api_path = f\"repos/{repo}/pulls?state=open&per_page=100\"\n        payload = _run_gh_json([\"gh\", \"api\", \"--paginate\", api_path])\n        payload = _limit_payload(payload, limit)\n    if not fetch_files:","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/scripts/pr_blocker_audit.py#L143-L179","documentation":"Raised by load_json_file in scripts/pr_blocker_audit.py when opening or reading the given path raises OSError — the file does not exist, is a directory, or the process lacks read permission. Like the JSON error, it is normalized to ValueError with the path embedded, so the audit script reports a uniform error for unusable input files.","triggerScenarios":"Passing a wrong/misspelled --input path; relative path resolved from a different working directory; pointing at a directory instead of a file; permission bits or sandboxing denying read access; a path containing an unexpanded ~ or shell variable.","commonSituations":"Running the script from a different cwd so a relative snapshot path misses; typos in long filenames; the snapshot file was moved or deleted between capture and audit; running under a restricted container without volume read access.","solutions":["Confirm the file exists at the exact path: ls -l <path> from the same directory you run the script from.","Use an absolute path to eliminate cwd ambiguity.","Fix permissions (chmod +r) or copy the file somewhere readable if running in a restricted environment.","Expand any ~ or $VAR manually: use realpath <path> to get the literal location."],"exampleFix":"# before\n$ python scripts/pr_blocker_audit.py --input prs.json   # run from another dir\nValueError: could not read prs.json: [Errno 2] No such file or directory\n\n# after\n$ python scripts/pr_blocker_audit.py --input /abs/path/to/prs.json","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef check_readable_file(path: str) -> Path:\n    p = Path(path).expanduser().resolve()\n    if not p.is_file():\n        raise FileNotFoundError(f'not a file: {p}')\n    if not p.stat().st_size:\n        raise ValueError(f'empty file: {p}')\n    return p","typeGuard":"import os\n\ndef is_readable_file(path: str) -> bool:\n    return os.path.isfile(os.path.expanduser(path)) and os.access(os.path.expanduser(path), os.R_OK)","tryCatchPattern":"try:\n    payload = load_json_file(Path(args.input))\nexcept ValueError as e:\n    if 'could not read' in str(e):\n        print(f'Check path/permissions: {e}', file=sys.stderr)\n    raise SystemExit(2)","preventionTips":["Pass absolute paths to CLI tools; resolve ~ with expanduser yourself.","Assert the file exists and is non-empty immediately after capturing it, not at audit time.","Run the script from the directory containing the snapshot, or derive paths from a known root."],"tags":["filesystem","cli","python","validation"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}