nexu-io/open-design · error · SystemExit
[last30days] Cannot read --synthesis-file: {exc}
Error message
[last30days] Cannot read --synthesis-file: {exc} What it means
read_synthesis_file() expands the user path and calls Path.read_text(encoding='utf-8'). On any OSError (file missing, permission denied, ISDIR, broken symlink, decode-adjacent read failure) it writes a `[last30days] Cannot read --synthesis-file: <exc>` line to stderr and re-raises as SystemExit(2). The exception object is interpolated verbatim so the underlying errno/path is visible.
Source
Thrown at design-templates/last30days/scripts/last30days.py:200
slug = slugify(topic)
extension = "json" if emit == "json" else "html" if emit == "html" else "md"
raw_label = "raw-html" if emit == "html" else "raw"
suffix_part = f"-{suffix}" if suffix else ""
raw = path / f"{slug}-{raw_label}{suffix_part}.{extension}"
try:
home = _Path.home().resolve()
relative = raw.relative_to(home)
return f"~/{relative}"
except ValueError:
return str(raw)
def read_synthesis_file(path: str) -> str:
try:
return Path(path).expanduser().read_text(encoding="utf-8")
except OSError as exc:
sys.stderr.write(f"[last30days] Cannot read --synthesis-file: {exc}\n")
raise SystemExit(2)
def persist_report(report: schema.Report) -> dict[str, int]:
import store
store.init_db()
topic_row = store.add_topic(report.topic)
topic_id = topic_row["id"]
source_mode = ",".join(sorted(report.items_by_source)) or "v3"
run_id = store.record_run(topic_id, source_mode=source_mode, status="running")
try:
findings = store.findings_from_report(report)
counts = store.store_findings(run_id, topic_id, findings)
store.update_run(
run_id,
status="completed",
findings_new=counts["new"],
findings_updated=counts["updated"],View on GitHub (pinned to 5be4028344)
Solutions
- Check the path exists and is a regular file: `test -f <path>`.
- Check read permission: `ls -l <path>`; chmod if needed.
- Use an absolute path to avoid ambiguity.
- Ensure the file is UTF-8 decodable (the read uses encoding='utf-8').
Example fix
# before python3.12 last30days.py --topic x --synthesis-file ~/pres/synth.mdr # after (fix typo) python3.12 last30days.py --topic x --synthesis-file ~/pres/synth.md
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
p = Path(path).expanduser()
if not p.is_file():
raise FileNotFoundError(f'--synthesis-file not a readable file: {p}')
text = p.read_text(encoding='utf-8') Try / catch
from pathlib import Path
try:
synthesis = Path(path).expanduser().read_text(encoding='utf-8')
except OSError as exc:
print(f'[last30days] Cannot read --synthesis-file: {exc}', file=sys.stderr)
sys.exit(2) Prevention
- Use absolute paths for file arguments.
- Validate existence with os.path.isfile before calling the script.
When it happens
Trigger: `--synthesis-file ~/notes/synth.md` where the file does not exist, is a directory, has no read permission, or is on an unreadable mount.
Common situations: Typo in the path; ~ not expanded by the shell because the arg was quoted oddly (the code does call expanduser, so this is rare); permissions locked down; file on a disconnected network mount; pointing at a directory by mistake.
Related errors
- [CompetitorsPlan] Cannot read plan file: {exc}
- Unknown search source: {source}
- --search requires at least one source.
- Unsupported emit mode: {emit}
- [CompetitorsPlan] Invalid JSON: {exc}
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/089805eb38920233.
Report an issue: GitHub.