mvanhorn/last30days-skill · error · HandoffContractError
Could not write nominations bundle {path}: {exc}
Error message
Could not write nominations bundle {path}: {exc} What it means
`write_nominations_bundle` raises HandoffContractError when creating the state dir or writing `discover-nominations.json` raises OSError. The comment states the design intent: a locked, read-only, or full disk is the protocol's clean exit-2 path, never a traceback. The message includes the target path and the underlying OS error.
Source
Thrown at skills/last30days/scripts/lib/discovery_handoff.py:332
list(enrichment_source_boundary)
if enrichment_source_boundary is not None
else None
),
"requested_sources": (
list(requested_sources) if requested_sources is not None else None
),
"lookback_days": int(lookback_days),
},
"nominations": rows,
}
path = nominations_bundle_path(state_dir)
try:
state_dir.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
except OSError as exc:
# A locked/read-only/full disk is the protocol's clean exit-2 path,
# never a traceback.
raise HandoffContractError(
f"Could not write nominations bundle {path}: {exc}"
) from exc
return NominationsBundle(
schema_version=schema.DISCOVERY_NOMINATIONS_SCHEMA_VERSION,
bundle_id=bundle_id,
generated_at=generated_at,
from_date=from_date,
to_date=to_date,
domain=domain,
tier=tier,
enrichment_source_boundary=(
list(enrichment_source_boundary)
if enrichment_source_boundary is not None
else None
),
requested_sources=(
list(requested_sources) if requested_sources is not None else None
),View on GitHub (pinned to c7460f6114)
Solutions
- Check the path named in the message: `ls -ld <dir>` and `df -h <dir>` for permission and space.
- Fix ownership/permissions (`chown -R "$USER" <dir>` or chmod u+w) or free disk space.
- Point `--save-dir` at a known-writable location for this run and subsequent legs.
- Remove a stale locked file at the bundle path if that is the blocker, then re-run the nominate-only sweep.
Example fix
# before: config dir owned by root sudo mkdir -p ~/.config/last30days # created as root python3 last30days.py "topic" --discover --nominate-only # after sudo chown -R "$(id -un)" ~/.config/last30days && python3 last30days.py "topic" --discover --nominate-only
Defensive patterns
Strategy: try-catch
Validate before calling
from pathlib import Path
def store_is_writable(state_dir: Path) -> bool:
try:
state_dir.mkdir(parents=True, exist_ok=True)
probe = state_dir / ".write-probe"
probe.write_text("x", encoding="utf-8")
probe.unlink()
return True
except OSError:
return False Try / catch
from lib import discovery_handoff
try:
bundle = discovery_handoff.write_nominations_bundle(...)
except discovery_handoff.HandoffContractError as exc:
raise SystemExit(2) from exc # clean exit; message names path + OS error Prevention
- Pre-flight a write probe in the chosen save dir before launching a paid sweep.
- Keep handoff state off network/locked mounts; use local disk.
- Never create the config dir with sudo — it ends up root-owned.
When it happens
Trigger: `--save-dir` on a read-only mount; `~/.config/last30days/` owned by another user; disk full at write time; an immutable/locked file at the bundle path; SELinux/AppArmor denying writes.
Common situations: Shared servers where the config dir was created by root; macOS Full Disk Access blocking writes under certain protected paths; CI runners with small tmpfs; a leftover root-owned `discover-nominations.json` from a sudo run.
Related errors
- Could not read {label.lower()} {path}: {exc}
- No handoff location available to write the nominations bundl
- Could not read {label} file {file_path}: {exc}
- No discovery nominations bundle found. Searched:\n{_searched
- {label} {path} is not valid JSON: {exc}
AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15).
Data as JSON: /api/errors/8c51589dee2588a9.
Report an issue: GitHub.