mvanhorn/last30days-skill · error · HandoffContractError

The {label} file is bound to bundle_id {file_bundle_id!r} bu

Error message

The {label} file is bound to bundle_id {file_bundle_id!r} but the {noun} is {bundle.bundle_id!r}. {location_label}:\n{_searched_lines(searched)}\nCorrect the bundle_id field in your {label} file to {bundle.bundle_id!r} and re-run this same leg.

What it means

Raised by _require_bundle_binding when a host file (judgments/angles) carries a bundle_id that does not match the bundle_id of the nominations bundle or pending report the engine is currently operating on. The handoff protocol binds every host file to one bundle so stale judgments from a previous run are never silently applied to a new nomination set. The message includes every bundle/pending-report path searched so the operator can find the current ID.

Source

Thrown at skills/last30days/scripts/lib/discovery_handoff.py:667

    pending report on the finalize leg - so a host's retry is not misdirected
    at the nominations bundle. A mismatch means the host echoed the wrong id
    into an otherwise-current file, so the remedy is the cheap one - correct
    the bundle_id field and re-run this same leg - never the expensive
    re-sweep/resume remedies (those belong to missing/stale state)."""
    file_bundle_id = str(payload.get("bundle_id") or "")
    if file_bundle_id == bundle.bundle_id:
        return
    if isinstance(bundle, PendingReport):
        searched = _search_paths(save_dir, config_dir, pending_report_path)
        noun = "current pending discovery report"
        location_label = "Pending-report locations searched"
    else:
        searched = _search_paths(save_dir, config_dir, nominations_bundle_path)
        noun = "current nominations bundle"
        location_label = "Bundle locations searched"
    if not searched and bundle.path is not None:
        searched = [bundle.path]
    raise HandoffContractError(
        f"The {label} file is bound to bundle_id {file_bundle_id!r} but the "
        f"{noun} is {bundle.bundle_id!r}. {location_label}:\n"
        f"{_searched_lines(searched)}\n"
        f"Correct the bundle_id field in your {label} file to "
        f"{bundle.bundle_id!r} and re-run this same leg."
    )


def _truncate_at_word(text: str, max_chars: int) -> str:
    """Cap ``text`` at ``max_chars``, cutting back to a word boundary and
    stripping trailing punctuation. Text within the cap passes through
    untouched."""
    if len(text) <= max_chars:
        return text
    return text[:max_chars].rsplit(" ", 1)[0].rstrip(_TRUNCATE_STRIP_CHARS)


def _sanitized_name(raw: object) -> str | None:

View on GitHub (pinned to c7460f6114)

Solutions

  1. Read the current bundle_id from the bundle/pending-report path listed in the error's searched-locations lines and set the bundle_id field in your host file to exactly that value, then re-run the same leg.
  2. If the stale file is from an abandoned run, regenerate the judgments/angles file against the current bundle instead of editing the old one.
  3. If you expected the old bundle to still be current, check that you are running with the same --save-dir / config dir as the run that produced it.

Example fix

// before (judgments.json)
{
  "bundle_id": "3f0c9a...-old-run",
  "judgments": []
}

// after
{
  "bundle_id": "<bundle_id printed by the error / found in the searched bundle path>",
  "judgments": []
}
Defensive patterns

Strategy: validation

Validate before calling

import json

def bundle_id_matches(path: str, bundle) -> bool:
    payload = json.loads(open(path, encoding="utf-8").read())
    return payload.get("bundle_id") == bundle.bundle_id

Try / catch

try:
    load_judgments(path, bundle, ...)
except HandoffContractError as e:
    # the message lists every searched bundle path; read the current id from there
    current = extract_bundle_id_from_error(e)  # then rewrite the host file and re-run

Prevention

When it happens

Trigger: Re-running a discovery leg after the engine regenerated the nominations bundle (new bundle_id) while reusing a judgments/angles file written for the old run; hand-copying an example judgments file with a placeholder bundle_id; two concurrent runs sharing a save_dir with different bundles.

Common situations: Iterating on judgments across legs: the user edits the file, re-runs, and the engine has already produced a fresh pending report with a different ID; using a file from a different machine or save_dir; editing bundle_id by hand and introducing a typo or keeping quotes from the error message (the repr includes quotes — paste the inner value only).

Related errors


AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15). Data as JSON: /api/errors/c66650540e0590eb. Report an issue: GitHub.