Repository navigation
Closed
Labels
Description
Summary
Opening a session URL directly in the Web UI (/server/{serverKey}/session/{sessionID}) boots the app, but the main content area stays empty and the message timeline is never rendered. Navigating from the project/session list works in the user's browser, but the direct URL fails silently.
Environment
- opencode version: 0.0.0-beta-17728
- OS: Linux 7.0.0-29-generic (Ubuntu) x86_64
- Terminal: TERM_PROGRAM=Orca TERM=xterm-256color COLORTERM=truecolor
- Shell: /bin/bash
- Install/channel: beta
- Server: background service http://0.0.0.0:49374
Reproduction
- Create a session:
opencode2 api post /api/session -d '{"location":{"directory":"/home/nico"}}' - Open
http://localhost:49374/server/{serverKey}/session/{sessionID}in a fresh browser context - The app boots (BETA badge, Home, New session buttons appear) but
mainarea stays empty - Console shows no errors; all asset/API requests return 200 (
/api/session/active,/api/project,/api/worktree/*)
Expected Behavior
The session page should render the session timeline (messages) after loading the URL directly.
Actual Behavior
The app boots but never fetches/renders the session's messages (/api/session/{id}/... is never requested). The main area is blank with no error, toast, or failure message.
Additional Context
- Reproduced with Chrome DevTools MCP in a real browser (not just headless)
- Authorization can be provided via URL-embedded credentials or by setting the Authorization header for all requests (fixes secondary 401s like
/site.webmanifest) - Related symptom: the "Auto-accept permissions" toggle in settings is grayed out because
serverSync().session.lineage.peek(id)?.session.directoryresolves to undefined (session not loaded) — System'screatePermissionScopeController.enableddepends on it - Related known issues (same class: web client session-state not loaded): Web: Sidebar session list hides worktree/sandbox sessions after 1.2.6 upgrade (filters to current directory only) #14082, Web UI on Windows: sessions not displayed due to path separator mismatch in /session API queries #25565, [Regression] v1.17.13 web UI session list still empty — fixes from #30167/#30314/#30804 not cherry-picked to stable #35340
Suggested investigation
- Validate that the session route forces a session sync / message fetch on direct navigation
- Check why the session lineage is not populated when entering via URL without the sidebar/project flow
Activity
nico2525nn commentedon Aug 20, 2026
Follow-up investigation (verified with a real browser via Chrome DevTools MCP):
The blank page is NOT about browser profiles or "fresh context" by itself. The root cause is a split between two state layers:
Session content / messages are server-side (DB) — they display in any browser/profile/access as long as the URL is correct. Confirmed: a private tab and a fresh (incognito-style) browser profile could both display the session normally.
The home/project sidebar list is client-side localStorage, persisted per server identity (the base64 server URL in the route), in
packages/app/src/context/server.tsx(projects: Record<string, StoredProject[]>persisted underPersist.global("server", ["server.v3"]), consumed byhome.project.forServer(conn)).Because the same backend is exposed under multiple URLs (
localhostand a Tailscale hostname), each URL becomes a separate server identity in the Web UI:This also explains the "projects disappear / not synced" reports: the sidebar is filtering by which server identity the current browser connection is bound to.
Suggested fix direction: key the home project list by a server-side identifier (e.g., projectID or the canonical worktree path) instead of the URL-derived server key, or merge project lists for connections pointing at the same backend, so the sidebar is consistent regardless of which URL (localhost vs tailnet hostname) is used to reach the same server.
TomKalina commentedon Aug 26, 2026
Reproducing on v1.18.23 with a different symptom than @nico2525nn's follow-up describes — direct URL navigation does NOT load the requested session's messages, even though the server-side API has them.
Repro:
ses_A(e.g. created viaPOST /api/session+ a prompt) on a server athttp://100.97.238.38:4096. Server detail endpoint returns it fine:GET /api/session/ses_A→ 200 withdata.location.directory = "/Users/.../dev".http://100.97.238.38:4096is in localStorage as a known server with at least one project added), open the direct URL the UI itself generates when navigating from the sidebar:http://100.97.238.38:4096/server/{base64("http://100.97.238.38:4096")}/session/ses_A/server/:key/session/:id, then the URL bar changes to/server/{...}/session/ses_Bwhereses_Bis some other session (in my caseses_fc2934cc1ffeEHx0xfH0t04ZhI— title "New session - 2026-08-26T09:35:29.091Z", created 2026-08-26T09:35:29, alsodirectory=/Users/.../dev). The main area shows the empty "New session" editor; no/api/session/ses_A/messagerequest is made.Expected: UI loads
ses_Aand renders its messages.Actual: UI redirects to a different session ID and shows an empty editor. The requested session's messages are never fetched.
Differs from @nico2525nn's follow-up: they reported "the session itself still loads, since sessions come from the server DB" — i.e. only the sidebar/projects list was broken on URL navigation. In my repro the session itself is also dropped and replaced with a different one. Possibly version-specific (mine 1.18.23 vs theirs 0.0.0-beta-17728).
Workaround I'm shipping for my dashboard: a custom modal session viewer that proxies
GET /api/session/{id}andGET /api/session/{id}/messageand renders the timeline inline. Would prefer to drop it once this is fixed.TomKalina commentedon Aug 26, 2026
Additional repro detail (v1.18.23): navigating via the sidebar session list does render messages correctly, but only the direct URL navigation breaks.
Steps:
http://100.97.238.38:4096/→ UI boots, redirects to/server/{key}/session/ses_X. Sidebar shows session list fine. But main area is empty (just the "New session" editor, no messages forses_X)./server/{key}/session/ses_Y) and paste into a fresh tab → UI boots, lands on the correct route, but main area is empty again — no/api/session/{id}/messagerequest fired.So the URL→route matching itself seems to work (no "Invalid server route" error, no redirect to a different session), but the message-fetching effect is not triggered on direct navigation. It only fires when the route transition originates from inside the SPA (sidebar click).
Server logs show the
/api/session/{id}(detail) request is made on both paths, but/api/session/{id}/messageonly on the sidebar-click path.Hope that helps narrow the scope.
nico2525nn commentedon Aug 28, 2026
Resolved in build 0.0.0-beta-18414 (verified): opening a session URL directly (
/server/:serverKey/session/:id) now renders the session (header, composer, and message timeline) as expected. Closing as resolved.