Title: [Bug]: New thread in a freshly-created project gets stuck on "Loading messages..." forever, even though the backend completes the turn
Area: apps/desktop
Steps to reproduce:
- Point T3 Code at a project folder whose path recently changed on disk (e.g. moved from
~/Desktop/Projects/foo to ~/Projects/foo), such that the old sidebar entry no longer resolves cleanly.
- Open/select that project and send the very first message in a brand-new thread.
- Observe: T3 silently creates a second, duplicate project record for the same folder (confirmed via
~/.t3/userdata/state.sqlite, projection_projects — two rows with the same title and different workspace_root casing/path, one created seconds before the new thread).
- The new thread's turn actually completes successfully server-side within ~10 seconds (all
orchestration_events for the thread — thread.created → thread.message-sent → thread.turn-start-requested → several thread.session-set → thread.message-sent (assistant) → thread.activity-appended → final thread.session-set (status ready) → thread.meta-updated — fire and complete cleanly, no errors).
- Despite this, the composer UI stays on "Loading messages..." indefinitely. The main content pane never renders anything (not even the two messages that exist in
projection_thread_messages).
Expected behavior: The thread should render the completed turn's messages and clear the loading state, exactly as it does in every other (non-brand-new) project's threads.
Actual behavior: The composer shows "Loading messages..." forever. Typing and clicking send is a silent no-op (text stays in the box, no new turn starts, sidebar timestamp never updates). Switching to model Sonnet+Low, navigating away to a different thread and back, and reloading did not clear it. state.sqlite shows the turn is state=completed, the thread session status=ready, last_error is null, and both the user and assistant messages exist in full with is_streaming=0. So this is purely a client-side rendering/subscription bug, not a backend failure — my best guess is a race where the renderer's live-event subscription for the thread attaches after the whole event burst (all 16 events within ~12s) has already fired, so it's left waiting on a "loaded" signal that already happened and never arrives again.
Impact: Blocks work completely (on that one thread — have to abandon it and start a new thread, which works fine).
Version: 0.0.40 (macOS, Alpha)
Environment: macOS 25.5.0 (Darwin), T3 Code (Alpha) 0.0.40
Workaround: None found that recovers the stuck thread (tried: switching model, switching threads and back, retyping and resending). Only workaround is to delete/archive the stuck thread and start a new one in the same project, which loads normally.
Secondary bug also observed: T3 silently created a duplicate project entry for the same on-disk folder (reachable via two path spellings due to a symlink, ~/Desktop/Projects/foo -> ~/Projects/foo) instead of resolving to the existing project record. This orphaned the new thread in a project with zero prior history, likely contributing to the race above (a project with no established event history has its very first thread hit the full burst-of-events-before-subscription race described above).
Title: [Bug]: New thread in a freshly-created project gets stuck on "Loading messages..." forever, even though the backend completes the turn
Area: apps/desktop
Steps to reproduce:
~/Desktop/Projects/footo~/Projects/foo), such that the old sidebar entry no longer resolves cleanly.~/.t3/userdata/state.sqlite,projection_projects— two rows with the sametitleand differentworkspace_rootcasing/path, one created seconds before the new thread).orchestration_eventsfor the thread —thread.created→thread.message-sent→thread.turn-start-requested→ severalthread.session-set→thread.message-sent(assistant) →thread.activity-appended→ finalthread.session-set(statusready) →thread.meta-updated— fire and complete cleanly, no errors).projection_thread_messages).Expected behavior: The thread should render the completed turn's messages and clear the loading state, exactly as it does in every other (non-brand-new) project's threads.
Actual behavior: The composer shows "Loading messages..." forever. Typing and clicking send is a silent no-op (text stays in the box, no new turn starts, sidebar timestamp never updates). Switching to model Sonnet+Low, navigating away to a different thread and back, and reloading did not clear it.
state.sqliteshows the turn isstate=completed, the thread sessionstatus=ready,last_erroris null, and both the user and assistant messages exist in full withis_streaming=0. So this is purely a client-side rendering/subscription bug, not a backend failure — my best guess is a race where the renderer's live-event subscription for the thread attaches after the whole event burst (all 16 events within ~12s) has already fired, so it's left waiting on a "loaded" signal that already happened and never arrives again.Impact: Blocks work completely (on that one thread — have to abandon it and start a new thread, which works fine).
Version: 0.0.40 (macOS, Alpha)
Environment: macOS 25.5.0 (Darwin), T3 Code (Alpha) 0.0.40
Workaround: None found that recovers the stuck thread (tried: switching model, switching threads and back, retyping and resending). Only workaround is to delete/archive the stuck thread and start a new one in the same project, which loads normally.
Secondary bug also observed: T3 silently created a duplicate project entry for the same on-disk folder (reachable via two path spellings due to a symlink,
~/Desktop/Projects/foo->~/Projects/foo) instead of resolving to the existing project record. This orphaned the new thread in a project with zero prior history, likely contributing to the race above (a project with no established event history has its very first thread hit the full burst-of-events-before-subscription race described above).