Repository navigation
Description
Bug Report: opencode web — project added via typed path stores raw input, then home session list silently shows 0 sessions
Environment
- opencode: 1.18.27 (Windows, npm install, win32 native — not WSL)
- Server:
opencode web --port 4096 --hostname 0.0.0.0started from the project directory - Client: Android mobile browser (also reproducible logic-wise on desktop) over LAN
- Frontend bundle served by 1.18.27 (
/assets/index-*.js)
Summary
Two related frontend defects in the web app's "open project" flow combine into a silent failure:
the project card renders normally (correct folder name) but the home session list shows
"Nothing here yet" forever, with no error anywhere.
-
The directory picker stores the raw typed string as the project identity.
When the user submits a path by pressing Enter/Go (instead of clicking a suggestion row),
the raw input is normalized for slashes only — drive-letter / path casing is not resolved
against the filesystem. On mobile, IME suggestions and composition input make it trivial
to end up with e.g.D:\workSpace\opencode-tmpinstead ofD:\WorkSpace\opencode-tmp. -
Home session grouping is case-sensitive on Windows.
Sessions are grouped/filtered by a path key that canonicalizes slashes but not case
(pathKey()inpackages/app/src/utils/path-key.ts). Windows paths are case-insensitive
(NTFS), and the server API is already case-insensitive (verified below), so the frontend is
the only layer that treatsD:/workSpace/...≠D:/WorkSpace/.... The mismatched project
therefore matches zero sessions and renders an empty list with no diagnostics.
Additionally, a usability trap that amplified confusion during debugging:
3. The suggestion list mixes the matched directory and its children (opencode-tmp/ and
opencode-tmp/_smoke/); on narrow screens rows are truncated to the same prefix and are
indistinguishable before tapping.
Reproduction (deterministic, no phone needed)
- Start
opencode webon Windows from a project dir, e.g.D:\WorkSpace\opencode-tmp
(not a git repo → project resolves to the "global" pseudo-project; sessions are keyed by
the exact directory stringD:/WorkSpace/opencode-tmpin the DB). - Create a couple of sessions from the TUI.
- Open the web UI, "Add project", type the path with any casing difference
(e.g.D:\workSpace\opencode-tmp) and confirm with Enter (do not click the suggestion row). - The project card is added, titled
opencode-tmp(looks completely normal). - Home session list for that card: 0 sessions, no error. TUI sessions never appear.
On mobile the step-3 casing slip happens easily because IME composition/autocorrect
(also full-width punctuation like / \ ?) bypasses or mis-targets the suggestion rows;
submitting via the IME "Go/Enter" stores the raw string. Server logs confirm the wrong-case
directory reaching the server and an instance being created for it:
timestamp=... message="watcher backend" directory="D:\\workSpace\\opencode-tmp" platform=win32
Evidence that each layer behaves differently
| Layer | Input d:/workspace/opencode-tmp (any case/slash/trailing-slash variant) |
Result |
|---|---|---|
| Windows FS | Test-Path D:\workSpace\opencode-tmp |
exists (case-insensitive) |
Server GET /session?directory=... |
all variants incl. \, /, trailing \, lowercase |
returns all 3 sessions |
| Web frontend grouping | pathKey(session.directory) ∈ projectDirectories.map(pathKey) |
0 sessions for wrong-case project |
Relevant code:
packages/app/src/utils/path-key.ts—pathKey()canonicalizes slashes only; no case folding
for Windows drive paths.packages/app/src/pages/home/home-controller.ts—
projects().find((project) => project.worktree === selection().directory)(strict equality),
andprojects.open(s)stores{ worktree: s }with the raw string and an exact-match
duplicate check, so a wrong-case duplicate card can coexist with the correct one and both
look identical in the UI.- Home session filter (bundle,
_et):sessions.filter(r => projectDirectories.has(Ke(r.directory))).
Expected behavior
- Submitting a typed path should resolve it against the filesystem and store the real,
FS-canonical casing (like native OS file pickers do), regardless of Enter/Go vs suggestion click. - On Windows, project↔session matching should be case-insensitive (
pathKey()should
lowercase drive-letter paths, mirroringpickerRelativePath()which already does). - A full-width IME character (
/\?etc.) in the picker input should be normalized to ASCII
or rejected with a clear message; currently it degrades into a misleading
"folder not found" or a silently-broken project entry. - Suggestion rows mixing the matched folder with its children should render the distinguishing
suffix (or indent children) so they are not truncated to identical text on narrow screens.
Workaround for affected users
Remove the broken project card, then add the project by pasting the correctly-cased path
(copy from the PC) and clicking the app's suggestion row (never the IME's Enter/Go).
After that, sessions display normally (verified end-to-end with mobile emulation).
Notes
- Server log also shows a
MaxListenersExceededWarning(11 listeners on an EventTarget) when
several clients/instances connect — likely listener leak in the event bus; separate issue.
Activity
github-actions commentedon Sep 4, 2026
This issue doesn't fully meet our contributing guidelines.
What needs to be fixed:
...— a placeholder left unchanged from the template. Please update it to a concise, descriptive title that reflects the actual bug (e.g. the title in the issue body would work well).Please edit this issue to address the above within 2 hours, or it will be automatically closed.
This issue might be a duplicate of existing issues. Please check:
If you believe this was flagged incorrectly, please let a maintainer know.
github-actions commentedon Sep 4, 2026
This issue has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window.
Feel free to open a new issue that follows our issue templates.