You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
web: sessions not grouped under project on homepage when the same directory is loaded with two drive-letter cases (D:\ vs d:\) #51797
On Windows, the same directory gets loaded twice by the location services — once with an uppercase drive letter (D:\Codes\processv3) and once with a lowercase one (d:\Codes\processv3) — so /api/debug/location reports two entries for one folder. The Web UI homepage groups sessions by exact string match against project directories, and because the session's stored location.directory doesn't string-match the project list, all sessions for that project are filtered out. The project row itself shows up exactly once in the sidebar, but clicking it (or F5) shows no sessions under it — the conversations effectively "disappear" from the project grouping even though the server-side data is correct.
Expected Behavior
Sessions should be grouped under their project on the homepage regardless of drive-letter case. D:\Codes\processv3 and d:\Codes\processv3 are the same directory on Windows and should resolve to one location (and one match) — or at minimum the frontend comparison should be case-insensitive on win32.
Actual Behavior
The location registry holds two entries for the same folder (upper- and lowercase drive letter).
Server-side data is correct: sessions carry projectID=fd413c6b… matching the processv3 project row, and GET /api/session?project=… returns them.
The Web UI homepage filters sessions by comparing session.location.directory against the project directory list with exact string matching, so the sessions are dropped from the UI. The conversations never appear under the project group.
Plugins
no
OpenCode version
v2.0.18
Steps to reproduce
On Windows, start the opencode service and open the Web UI homepage (/).
Make sure the same directory is reachable under two drive-letter spellings (e.g. a session/TUI was launched with d:\Codes\processv3 at some point while the service also booted D:\Codes\processv3).
Open GET /api/debug/location — the directory appears twice:
Query sessions by project id — they are all there and correctly linked:
GET /api/session?project=fd413c6b402e04c300e1d97956417119bf671ed7
-> 3+ sessions, each with "location":{"directory":"D:\\Codes\\processv3"}
Query sessions by the lowercase directory (the spelling the client keeps using) — empty:
GET /api/session?directory=d%3A%5CCodes%5Cprocessv3
-> {"data":[],"cursor":{"previous":null,"next":null}}
On the Web UI homepage, the project D:\Codes\processv3 appears exactly once in the project list, but no sessions are grouped under it. Clicking the project entry or pressing F5 does not bring the sessions back.
Thanks for the detailed report. I was able to reproduce this, both on v2.0.18 and on the latest dev (86ce19d). The sandbox runs Linux, so I checked the two code paths you point to directly rather than running a real Windows server:
Web UI home page: with a project at d:\Codes\processv3 and a session whose location.directory is D:\Codes\processv3, the home page's session filter returns no sessions. It compares directories with a case-sensitive key, even though other path helpers in the codebase already ignore drive-letter case on Windows.
Server: with win32 simulated, the step that normalizes location directories keeps D:\Codes\processv3 and d:\Codes\processv3 as two different keys. That fits the two entries you saw in /api/debug/location.
The script below runs both checks. Until this is fixed, opening the project with the same drive-letter case every time should keep the sessions grouped. A related fix for the same kind of case mismatch elsewhere is #53349.
Reproduction script (repro.sh)
#!/usr/bin/env bash# Repro for #51797: Windows drive-letter case variants (D:\ vs d:\) are treated as# different directories by core's Location canonicalization and by the web Home# session filter. Runs against an opencode checkout (default /workspace/repo).# The core check simulates win32 by overriding process.platform (sandbox is Linux).set -euo pipefail
REPO="${1:-/workspace/repo}"
APP_TEST="$REPO/packages/app/src/home/sessions/repro-51797.test.ts"
CORE_TEST="$REPO/packages/core/test/repro-51797.test.ts"trap'rm -f "$APP_TEST" "$CORE_TEST"' EXIT
cat >"$APP_TEST"<<'EOF'import { expect, test } from "bun:test"import type { SessionInfo } from "@opencode/client/promise"import type { LocalProject } from "@/shell/state/layout"import { buildHomeSessionRecords } from "./records"test("#51797 home groups sessions whose drive letter differs only in case", () => { const project = { id: "p", worktree: "d:\\Codes\\processv3" } as LocalProject const session = { id: "s1", projectID: "p", title: "s1", location: { directory: "D:\\Codes\\processv3" }, time: { created: 1, updated: 1 }, } as SessionInfo const records = buildHomeSessionRecords({ sessions: () => [session], projectDirectories: () => ["d:\\Codes\\processv3"], projects: () => [project], }) console.log("home records for project d:\\Codes\\processv3:", records.map((r) => r.session.id)) expect(records.map((r) => r.session.id)).toEqual(["s1"])})EOF
cat >"$CORE_TEST"<<'EOF'import { expect, test } from "bun:test"test("#51797 canonical location treats D:\\ and d:\\ as one directory on win32", async () => { Object.defineProperty(process, "platform", { value: "win32" }) const { LocationServiceMap } = await import("../src/location-service-map") const a = LocationServiceMap.canonical({ directory: "D:\\Codes\\processv3" } as any).directory const b = LocationServiceMap.canonical({ directory: "d:\\Codes\\processv3" } as any).directory console.log("canonical:", JSON.stringify(a), JSON.stringify(b)) expect(a).toBe(b)})EOFecho"== app: Home session filter =="
JSX_PRELOAD=""
[ -f"$REPO/packages/ui/test/solid-jsx.ts" ] && JSX_PRELOAD="--preload ../ui/test/solid-jsx.ts"
(cd "$REPO/packages/app"&& bun test --conditions=solid --isolate $JSX_PRELOAD --preload ./happydom.ts ./src/home/sessions/repro-51797.test.ts) ||trueecho"== core: LocationServiceMap.canonical (win32 simulated) =="
(cd "$REPO/packages/core"&& bun test ./test/repro-51797.test.ts) ||true
Activity
github-actions commentedon Sep 28, 2026
This issue might be a duplicate of existing issues. Please check:
For keybind-related issues, please also check our pinned keybinds documentation: #4997
opencodejr commentedon Oct 28, 2026
Thanks for the detailed report. I was able to reproduce this, both on v2.0.18 and on the latest
dev(86ce19d). The sandbox runs Linux, so I checked the two code paths you point to directly rather than running a real Windows server:d:\Codes\processv3and a session whoselocation.directoryisD:\Codes\processv3, the home page's session filter returns no sessions. It compares directories with a case-sensitive key, even though other path helpers in the codebase already ignore drive-letter case on Windows.D:\Codes\processv3andd:\Codes\processv3as two different keys. That fits the two entries you saw in/api/debug/location.The script below runs both checks. Until this is fixed, opening the project with the same drive-letter case every time should keep the sessions grouped. A related fix for the same kind of case mismatch elsewhere is #53349.
Reproduction script (repro.sh)
Run it:
bash repro.sh