[Bug]: Desktop startup stalls for 15-20s on multi-project setups due to synchronous git fetch and unindexed SQLite query before window creation
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Use T3 Code desktop with multiple registered projects (e.g. 20-30 repositories) and default settings (
"defaultAutoPull": true). - Accumulate thread activity history (e.g. 10k+ rows in
projection_thread_activities). - Quit the app and launch
t3code/t3code-nightlyon desktop. - Measure wall-clock time between launching the process and the main application window appearing.
Expected behavior
The desktop application window should appear within 1-2 seconds of launching. Long-running network operations (such as remote git fetching across all projects) and startup state reconciliations should run asynchronously in the background rather than blocking the desktop HTTP readiness probe and window creation.
Actual behavior
The application process starts immediately, but no window appears for 15-22 seconds (giving the impression that the app failed to launch or crashed). Once the window finally appears, the app runs fast and responsively.
Root cause analysis:
- Window creation is blocked on HTTP readiness: In
apps/desktop/src/backend/DesktopBackendManager.ts, the desktop main process probesGET /.well-known/t3/environmentbeforeapps/desktop/src/window/DesktopWindow.tscallscreateWindow(). - Global middleware blocks all HTTP traffic: In
apps/server/src/server.ts,commandReadinessLayerintercepts all HTTP requests and waits onstartup.awaitCommandReadybefore serving any route. - Heavy synchronous operations in
apps/server/src/serverRuntimeStartup.tsblockcommandGate.signalCommandReady:"projects.auto-pull"(line 976):autoPullProjects()iterates through every workspace root withdefaultAutoPullenabled (the default inDEFAULT_SERVER_SETTINGS) and callsgit.statusDetails(cwd)in batches of 4. This triggersrefreshStatusUpstreamIfStale->fetchRemoteForStatus(networkgit fetch) for each project sequentially. On setups with ~25 repositories, this takes 7-10 seconds over WiFi."worktree-setups.reconcile"(line 973):reconcileWorktreeSetupscallsquery.listActivitiesByKind("worktree-setup"). Inapps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts, this executes:
There is no index onSELECT a.* FROM projection_thread_activities a JOIN projection_threads t ON t.thread_id = a.thread_id WHERE a.kind = ? ...kindinprojection_thread_activities. In databases with 15k+ activities and heavypayload_jsoncolumns, this full scan and temporary B-tree sort takes 6+ seconds.
- Because the desktop probe timeout is 1000ms, the probe repeatedly times out with HTTP 499 until all startup phases complete ~15s later.
Related issues and why this is not a duplicate
- #2726: Reported a general slow desktop startup on
0.0.24, attributed to provider CLI probing and closed as resolved. This report covers the newerprojects.auto-pull(introduced in PR #9277) and the unindexedworktree-setups.reconcilequery added in recent releases. - PR #9277: Intended
autoPullProjectsto be non-blocking ("failures are non-blocking for startup and status refresh"), but placed it synchronously ahead ofcommandGate.signalCommandReady(line 1063). BecausecommandReadinessLayergates/.well-known/t3/environment, it blockscreateWindowinDesktopBackendManager.ts. - PR #10972: Attempted to defer auto-pull and splash earlier on Linux, but was closed unmerged on September 18 without addressing the unindexed SQL query or the architectural readiness gate.
- #9239 / #9246: Linux keyring / safe-storage stall; our credential store completes in <3ms.
- #8949: Runtime
shellSnapshotrepository identity caching after UI is open; our issue occurs before window creation and includes a 6.6s database query. - #10517: Backend crash-loop on macOS (
ECONNREFUSED); our backend does not crash, but is held by synchronous startup phases.
Impact
Major degradation or frequent failure
Version or commit
0.0.43-nightly.20260919.1962 (commit dfbb11bdd7c3), also observed across previous releases.
Environment
Arch Linux / Linux x86_64, Electron Desktop
Logs or stack traces
# From desktop.trace.ndjson:
13:27:37.750 | desktop.backendProcess.probeReadiness (15558.9ms)
13:27:38.724 | http.client GET /.well-known/t3/environment (1001ms) -> Interrupted / Timeout
... (13 retries timing out after 1000ms each) ...
13:27:53.054 | http.client GET /.well-known/t3/environment (195ms) -> 200 OK
13:27:53.252 | desktop.window.createWindow (55ms) # Window finally opens after 15.5s
# From server.trace.ndjson:
13:27:39.475 | server.startup.worktree-setups.reconcile (6637ms): sql.execute (no index on projection_thread_activities.kind)
13:27:46.112 | server.startup.projects.auto-pull (6976ms wall-clock, 118.5s cumulative across 4 threads):
GitVcsDriver.fetchRemoteForStatus across 25 repositories
13:27:53.054 | commandGate.signalCommandReady
Workaround
- Setting
"defaultAutoPull": falsein~/.t3/userdata/settings.jsoneliminates the 7-second network Git fetching phase during boot. - Adding
CREATE INDEX IF NOT EXISTS idx_projection_thread_activities_kind ON projection_thread_activities(kind);drops the worktree reconciliation query from ~6.6s to <1ms.
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 with apps/desktop/src/backend/DesktopBackendManager.ts and apps/desktop/src/window/DesktopWindow.ts, then trace commandReadinessLayer in apps/server/src/server.ts into serverRuntimeStartup.ts. Inspect ProjectionSnapshotQuery.ts and the startup trace timings, including the auto-pull and worktree reconciliation phases. Done means desktop window creation no longer waits on the reported long-running startup work and the reproduction startup timing improves without breaking readiness behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, sqlite, typescript
- Domain
- backend, database, desktop, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100