From 191f44ee02d02c1f8778246855dc071bf2c050e1 Mon Sep 17 00:00:00 2001 From: Matt Reason Date: Wed, 25 Feb 2026 11:26:41 -0800 Subject: [PATCH] fix: make rename replay idempotent to prevent cache rebuild failures When events.jsonl contains duplicate rename events (e.g. from repeated `pb update --parent=` operations on already-renamed issues), every write operation fails with "rename target matches current id" during cache rebuild. The sequence: 1. `pb update --parent=` emits a rename event 2. A subsequent `pb update --parent=` on the same issue emits another identical rename event 3. On cache rebuild, the first rename succeeds and adds a mapping to the renames table (old_id -> new_id) 4. The duplicate rename calls resolveIssueID(old_id) which follows the chain to new_id. Now resolvedOldID == newID, triggering the error Since events are appended to events.jsonl before RebuildCache runs, the write succeeds but the CLI exits with code 1. Every subsequent operation also fails because the stale cache triggers a rebuild that hits the same duplicate rename. The fix treats "resolvedOldID == newID" as a no-op (the rename was already applied) instead of an error, making event replay idempotent. Workaround for affected users: deduplicate rename events in events.jsonl and re-run `pb init`. Co-Authored-By: Claude Opus 4.6 --- internal/pebbles/db_apply.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pebbles/db_apply.go b/internal/pebbles/db_apply.go index 72a1078..e9e3643 100644 --- a/internal/pebbles/db_apply.go +++ b/internal/pebbles/db_apply.go @@ -221,7 +221,7 @@ func applyRename(db *sql.DB, event Event) error { return fmt.Errorf("rename target already mapped to %s", resolvedNewID) } if resolvedOldID == newID { - return fmt.Errorf("rename target matches current id") + return nil // already applied; idempotent replay } if err := ensureIssueExists(db, resolvedOldID); err != nil { return err