Skip to content

Fix silent startup crash when the saved session contains navigation pins#90

Merged
dovvnloading merged 1 commit into
mainfrom
hotfix/pins-restore-crash
Jul 21, 2026
Merged

Fix silent startup crash when the saved session contains navigation pins#90
dovvnloading merged 1 commit into
mainfrom
hotfix/pins-restore-crash

Conversation

@dovvnloading

Copy link
Copy Markdown
Owner

Summary

Root cause of "the app sits spinning and never opens": the session deserializer's _load_pins still called the legacy PinOverlay.clear_pins()/add_pin_button() - methods that don't exist on PinOverlayHost (what window.pin_overlay has been since Phase 5). The AttributeError aborted the entire chat restore at launch, the _handle_load_error recovery path then crashed on the same missing method, and the app exited with no window and exit code 0.

Purely data-dependent: it only fires when the saved session actually contains pins - which happened for the first time today when pins were created via the toolbar. Every empty-session test drive passed, which is how it survived Phase 5/6/7 verification.

All five stale legacy call sites removed (_load_pins x2, _handle_load_error, new_chat, and a remnant clear() in graphlink_connections.py). With the store-based design they're unnecessary: scene.clear() empties scene.pin_store (the overlay's reactive source of truth) and add_navigation_pin() registers restored pins in it.

Test plan

  • 3 regression tests using a pin_overlay with NO methods at all (a MagicMock would absorb the legacy calls and hide the bug): pins restore lands in the store, zero-pins is a no-op, and the load-error recovery path no longer raises
  • Full suite: 1686 passed, zero regressions
  • Verified against the real crashing session: app launches, restores the pinned chat, window up and staying

… pins

The session deserializer's _load_pins still called the LEGACY PinOverlay's
clear_pins()/add_pin_button() - methods that do not exist on PinOverlayHost
(window.pin_overlay since Phase 5). The AttributeError aborted the entire
chat restore at launch; _handle_load_error's recovery path then crashed on
the same missing method, and the app exited with no window - presenting as
"sits spinning and never opens." Purely data-dependent: nothing surfaced
until a session actually contained pins (created via the Pins UI earlier
today), which is why every empty-session test drive passed.

All five stale legacy call sites removed (deserializers._load_pins x2,
deserializers._handle_load_error, ChatWindow.new_chat, and a remnant
clear() in graphlink_connections.py): with the store-based Phase 5 design
they are unnecessary - scene.clear() empties scene.pin_store (the overlay's
reactive source of truth) and scene.add_navigation_pin() registers restored
pins in it.

Regression tests use a pin_overlay object with NO methods at all (a
MagicMock would absorb the legacy calls and hide the bug): pins restore
lands in the store without touching the overlay, and the load-error
recovery path no longer raises. Verified against the real crashing session:
the app now launches, restores the pinned chat, and stays up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dovvnloading
dovvnloading merged commit 6b1e428 into main Jul 21, 2026
2 checks passed
@dovvnloading
dovvnloading deleted the hotfix/pins-restore-crash branch July 21, 2026 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant