[Bug]: New thread in a freshly-created project gets stuck on "Loading messages..." forever, even though the backend completes the turn
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
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/footo~/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 sametitleand differentworkspace_rootcasing/path, one created seconds before the new thread). - The new thread's turn actually completes successfully server-side within ~10 seconds (all
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). - 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).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in apps/desktop and reproduce with a project whose path recently changed, then inspect the thread loading and live-event subscription behavior. Compare the UI state with state.sqlite, especially projection_projects, projection_thread_messages, and orchestration_events. Done means a first thread in the affected project renders its completed messages, clears "Loading messages...", and does not create a duplicate project record.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sqlite, typescript
- Domain
- databases, desktop, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100