Before submitting
Area
apps/web
Steps to reproduce
- Open the web client on an environment and view any thread, so the browser caches that environment's shell.
- Close the tab (or navigate away) so this client stops receiving live updates.
- Create a new thread in that environment somewhere else (another device or client, the CLI, or an agent).
- In the first browser, open a full-page link straight to the new thread:
/<environmentId>/<newThreadId>.
In my run, step 3 used the server's HTTP dispatch endpoint (thread.create), and steps 1, 2 and 4 used headless Chromium. Everything ran against an isolated local server with synthetic data, and the server and browser talked directly, with no transport manipulation.
Expected behavior
The link opens the new thread, which exists on the server, or at least waits until the client knows whether it exists.
Question for triage: what is the intended behavior while a client is still synchronizing? Should a thread link wait until the shell is live before it is treated as missing, and should already-available thread content be shown meanwhile?
Actual behavior
The client redirects to / and lands on an unrelated thread (the environment's New thread). It stays there after synchronization finishes, even though the target thread appears in the sidebar by then.
Measured in the run below: about 0.2 s after loading, the app is still on its splash screen at the target path. By 3.1 s the path has changed to an unrelated thread's, and it is unchanged at 8.1 s.
Likely cause, from source on main: apps/web/src/components/ThreadRouteView.tsx treats the route as bootstrapped as soon as any shell snapshot exists (bootstrapComplete = shell.data?.snapshot._tag === "Some", line 85 at 094fb230), and that includes a cached snapshot that predates the thread. With no detail loaded yet, the thread resolves as missing, and the effect navigates to /.
Impact
Minor bug or occasional failure
A link to a thread created since the client's last visit (from another device, a notification, or an agent) opens the wrong thread, and the user has to find the right one manually.
Version or commit
The web client was built from pingdotgg/t3code@35be904. ThreadRouteView.tsx and threadRoutes.ts are unchanged from there through current main 094fb230. The server was the same source, run with node apps/server/src/bin.ts --mode web.
Environment
macOS (Darwin 25.5, arm64), Node 24.12.0, headless Chromium (chromium-headless-shell 153.0.8010.12) at 1280×800. Only the web client was checked; desktop and mobile were not. The "Codex update available" toast in the captures comes from the test server probing the locally installed Codex CLI, and is unrelated.
Screenshots, recordings, or supporting files
Base 35be904: the link to Created elsewhere A lands on workspace / New thread (real time; GIF sampled at 10 fps, no cuts or speed changes):

Full MP4 · Screenshot 3 s after loading
For comparison: the same steps with the closed candidate fix from #10604 (1cd6689)
The link to Created elsewhere B stays on that thread. This only illustrates one possible intended behavior; it is not a request to merge that PR.

Screenshot 3 s after loading
Related, but not duplicates: #11502 (mobile now waits for thread deep-link hydration) and #10888 (iOS "Thread unavailable").
Before submitting
Area
apps/web
Steps to reproduce
/<environmentId>/<newThreadId>.In my run, step 3 used the server's HTTP dispatch endpoint (
thread.create), and steps 1, 2 and 4 used headless Chromium. Everything ran against an isolated local server with synthetic data, and the server and browser talked directly, with no transport manipulation.Expected behavior
The link opens the new thread, which exists on the server, or at least waits until the client knows whether it exists.
Question for triage: what is the intended behavior while a client is still synchronizing? Should a thread link wait until the shell is live before it is treated as missing, and should already-available thread content be shown meanwhile?
Actual behavior
The client redirects to
/and lands on an unrelated thread (the environment's New thread). It stays there after synchronization finishes, even though the target thread appears in the sidebar by then.Measured in the run below: about 0.2 s after loading, the app is still on its splash screen at the target path. By 3.1 s the path has changed to an unrelated thread's, and it is unchanged at 8.1 s.
Likely cause, from source on
main:apps/web/src/components/ThreadRouteView.tsxtreats the route as bootstrapped as soon as any shell snapshot exists (bootstrapComplete = shell.data?.snapshot._tag === "Some", line 85 at094fb230), and that includes a cached snapshot that predates the thread. With no detail loaded yet, the thread resolves as missing, and the effect navigates to/.Impact
Minor bug or occasional failure
A link to a thread created since the client's last visit (from another device, a notification, or an agent) opens the wrong thread, and the user has to find the right one manually.
Version or commit
The web client was built from
pingdotgg/t3code@35be904.ThreadRouteView.tsxandthreadRoutes.tsare unchanged from there through currentmain094fb230. The server was the same source, run withnode apps/server/src/bin.ts --mode web.Environment
macOS (Darwin 25.5, arm64), Node 24.12.0, headless Chromium (chromium-headless-shell 153.0.8010.12) at 1280×800. Only the web client was checked; desktop and mobile were not. The "Codex update available" toast in the captures comes from the test server probing the locally installed Codex CLI, and is unrelated.
Screenshots, recordings, or supporting files
Base
35be904: the link to Created elsewhere A lands on workspace / New thread (real time; GIF sampled at 10 fps, no cuts or speed changes):Full MP4 · Screenshot 3 s after loading
For comparison: the same steps with the closed candidate fix from #10604 (1cd6689)
The link to Created elsewhere B stays on that thread. This only illustrates one possible intended behavior; it is not a request to merge that PR.
Screenshot 3 s after loading
Related, but not duplicates: #11502 (mobile now waits for thread deep-link hydration) and #10888 (iOS "Thread unavailable").