calesthio/OpenMontage · error · KeyError

Cost entry {entry_id!r} not found

Error message

Cost entry {entry_id!r} not found

What it means

KeyError raised by CostTracker._find when no entry in self.entries has id == entry_id. All entry-scoped operations (reserve, settle, cancel, annotate) locate entries through _find, so any stale or mistyped id surfaces here. It signals the entry was never created, was removed, or belongs to a different cost log.

Source

Thrown at tools/cost_tracker.py:515

        }
        self.cost_log_path.parent.mkdir(parents=True, exist_ok=True)
        with open(self.cost_log_path, "w") as f:
            json.dump(data, f, indent=2)

    def _load(self) -> None:
        with open(self.cost_log_path) as f:  # type: ignore[arg-type]
            data = json.load(f)
        self.entries = data.get("entries", [])
        self.budget_total_usd = data.get("budget_total_usd", self.budget_total_usd)
        self._approved_tools = set(data.get("approved_tools", []))

    # ---- Helpers ----

    def _find(self, entry_id: str) -> dict[str, Any]:
        for entry in self.entries:
            if entry["id"] == entry_id:
                return entry
        raise KeyError(f"Cost entry {entry_id!r} not found")

    @staticmethod
    def _new_id() -> str:
        return uuid.uuid4().hex[:12]

    @staticmethod
    def _now() -> str:
        return datetime.now(timezone.utc).isoformat()

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Create the entry first: capture the id returned by add_estimate/log and pass that exact string to reserve/settle.
  2. If the id came from an earlier run, confirm you loaded the same cost_log_path (the log is reloaded on startup; entries must be in it).
  3. Guard lookups by checking `any(e['id'] == entry_id for e in tracker.entries)` before acting, or catch KeyError and re-create the entry.
  4. If multiple processes share a log, serialize writes so entries are not lost.

Example fix

# before
tracker.settle("abc123deadbee")  # typo -> KeyError('Cost entry ... not found')

# after
entry_id = tracker.add_estimate(tool="seedance_video", estimated_usd=0.5)
assert any(e["id"] == entry_id for e in tracker.entries)
tracker.settle(entry_id)
Defensive patterns

Strategy: validation

Validate before calling

def entry_exists(tracker, entry_id: str) -> bool:
    return any(e["id"] == entry_id for e in tracker.entries)

Type guard

def is_entry_id(value: str) -> bool:
    return isinstance(value, str) and len(value) == 12 and all(c in "0123456789abcdef" for c in value)

Try / catch

try:
    tracker.settle(entry_id)
except KeyError as e:
    if "not found" in str(e):
        entry_id = tracker.add_estimate(tool=tool, estimated_usd=est)  # recreate
        tracker.settle(entry_id)
    else:
        raise

Prevention

When it happens

Trigger: Calling reserve/settle/cancel with an id that was never logged via add_estimate, an id from a previous session's cost log file, or a typo/truncated id (ids are 12-hex-char strings from _new_id).

Common situations: Persisting entry ids across process restarts where cost_log_path points to a rotated/different file, concurrent writers overwriting the log, or passing the entry dict instead of its id string.

Related errors


AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15). Data as JSON: /api/errors/6d7914efd42aec56. Report an issue: GitHub.