"Sign All Pacts" ignores max pacts limit — stale closure bug #251

Closed
opened 2026-06-01 15:05:20 +02:00 by Anexim · 2 comments
Owner

Steps to reproduce:

  1. Open Debug tab → Pacts section
  2. Click "Sign All Pacts"

Expected: Only signs up to maxPacts (base 1, increased by pactCapacity prestige upgrade)

Actual: Signs ALL 49 pacts regardless of max pacts limit. Shows "Signed Pacts: 49 | Max Pacts: 1"

Root cause: In PactDebugSection.tsx, the signAllPacts function iterates over all guardian floors and calls forcePact(floor) for each. The forcePact function checks signedPacts.length >= maxPacts, but signedPacts is captured from the component's state at render time via closure. Since React hasn't re-rendered between iterations, signedPacts.length always sees the initial value (0), so the check never triggers.

Fix: In signAllPacts, either:

  • Read signedPacts.length from the store directly (usePrestigeStore.getState().signedPacts.length) inside the loop
  • Or collect all floors to sign first, then add them in a single batch up to the limit

Affected file: src/components/game/tabs/DebugTab/PactDebugSection.tsx (the signAllPacts function, lines ~115-121)

Store: usePrestigeStore (signedPacts, addSignedPact)

**Steps to reproduce:** 1. Open Debug tab → Pacts section 2. Click "Sign All Pacts" **Expected:** Only signs up to `maxPacts` (base 1, increased by `pactCapacity` prestige upgrade) **Actual:** Signs ALL 49 pacts regardless of max pacts limit. Shows "Signed Pacts: 49 | Max Pacts: 1" **Root cause:** In `PactDebugSection.tsx`, the `signAllPacts` function iterates over all guardian floors and calls `forcePact(floor)` for each. The `forcePact` function checks `signedPacts.length >= maxPacts`, but `signedPacts` is captured from the component's state at render time via closure. Since React hasn't re-rendered between iterations, `signedPacts.length` always sees the initial value (0), so the check never triggers. **Fix:** In `signAllPacts`, either: - Read `signedPacts.length` from the store directly (`usePrestigeStore.getState().signedPacts.length`) inside the loop - Or collect all floors to sign first, then add them in a single batch up to the limit **Affected file:** `src/components/game/tabs/DebugTab/PactDebugSection.tsx` (the `signAllPacts` function, lines ~115-121) **Store:** `usePrestigeStore` (signedPacts, addSignedPact)
Anexim added the ai:todo label 2026-06-01 15:05:20 +02:00
n8n-gitea was assigned by Anexim 2026-06-01 15:05:20 +02:00
Author
Owner

Starting fix. The stale closure bug is in signAllPacts — it reads signedPacts.length from the render-time closure, which is always 0 during the loop. Fix: read from store.getState() inside the loop.

Starting fix. The stale closure bug is in signAllPacts — it reads signedPacts.length from the render-time closure, which is always 0 during the loop. Fix: read from store.getState() inside the loop.
Author
Owner

Fixed stale closure bug in PactDebugSection.tsx. Both forcePact and signAllPacts now read signedPacts directly from usePrestigeStore.getState() instead of using the render-time closure value. This ensures the maxPacts check works correctly when signing multiple pacts in a loop. All 43 DebugTab tests pass.

Fixed stale closure bug in PactDebugSection.tsx. Both `forcePact` and `signAllPacts` now read `signedPacts` directly from `usePrestigeStore.getState()` instead of using the render-time closure value. This ensures the `maxPacts` check works correctly when signing multiple pacts in a loop. All 43 DebugTab tests pass.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Anexim/Mana-Loop#251