Bug: "Open project" / directory picker always shows "No folders found" — GET /file request missing required path query param
Summary
The "Open project" dialog (and the subfolder browser inside the "New Session" flow) always shows "No folders found", even when valid directories exist and the server's REST API works correctly when called directly. The root cause is a client/server API contract mismatch: the frontend calls the file-listing SDK method without the now-required path query parameter, so the server rejects every request with a 400.
This looks like a regression of the older #8325 (closed, fixed for a different endpoint/cause) — same user-visible symptom, different root cause.
Environment
- opencode server version: 1.18.8 (self-hosted
opencode web, behind an nginx reverse proxy on a custom domain)
- Client: web UI (Chrome), accessed via a domain other than
localhost
- Server started with an explicit project directory (single project scope), not
0.0.0.0/browsing from a multi-project root
Root cause
The server's own OpenAPI schema for GET /file marks path as required:
{
"name": "path",
"in": "query",
"schema": { "type": "string" },
"required": true
}
Confirmed directly against a running server:
# missing "path" -> 400
curl -u user:pass "https://<host>/file?directory=%2Fhome%2Fopencode"
# {"name":"BadRequest","data":{"message":"Missing key\n at [\"path\"]","kind":"Query"}}
# with "path=" (even empty) -> 200, real listing
curl -u user:pass "https://<host>/file?path=&directory=%2Fhome%2Fopencode"
# [{"name":".cache","path":".cache/", ...}, ...]
Server log confirms the rejection:
level=WARN message="schema rejection" kind=Query reason="Missing key\n at [\"path\"]"
But the frontend's directory-picker code calls the SDK's file.list() without a path field, in both the v1 and v2 directory pickers:
packages/app/src/components/directory-picker-domain.ts (~line 345):
const request = args.sdk.api.file
.list({ location: { directory: key } }) // <-- no `path` field
.then((result) => result.data)
.catch(() => []) // <-- error silently swallowed, becomes "No folders found"
packages/app/src/components/dialog-select-directory-v2.tsx (~line 130):
return sdk.api.file
.list({ location: { directory: absolute } }) // <-- same issue
.then((result) => ...)
Meanwhile, the SDK's own generated types (packages/sdk/js/src/v2/gen/types.gen.ts) show the correct/expected shape:
export type FileListData = {
body?: never
path?: never
query: {
directory?: string
workspace?: string
path: string // required, not optional
}
url: "/file"
}
So the call sites use an outdated { location: { directory } } shape instead of the flat { directory, path } shape the SDK types (and server) now require. Because the .catch(() => []) swallows the resulting 400 error, the UI shows an empty "No folders found" state with no visible error at all, making this very hard to diagnose from the UI alone.
Steps to reproduce
- Run
opencode web with a specific project directory (not the filesystem root/home), behind a reverse proxy on a non-localhost domain.
- Open the web UI, click "Open project" (or "Add project" from the New Session flow).
- Observe: "No folders found", regardless of what's typed in the search box or what directories actually exist.
- Open browser DevTools → Network tab → observe
GET /file?... (or /find/file?...) requests returning 400 Bad Request with {"message":"Missing key\n at [\"path\"]"}.
Expected behavior
The directory picker should list real folders, since the underlying REST API works correctly when called with the required path parameter.
Suggested fix
Update the call sites in directory-picker-domain.ts and dialog-select-directory-v2.tsx to include an explicit path: "" (or the correct relative path being browsed) alongside directory, matching the FileListData query shape. Also consider not silently swallowing HTTP errors in .catch(() => []) for this codepath, so future contract mismatches surface as a visible error rather than a confusing empty state.
Bug: "Open project" / directory picker always shows "No folders found" —
GET /filerequest missing requiredpathquery paramSummary
The "Open project" dialog (and the subfolder browser inside the "New Session" flow) always shows "No folders found", even when valid directories exist and the server's REST API works correctly when called directly. The root cause is a client/server API contract mismatch: the frontend calls the file-listing SDK method without the now-required
pathquery parameter, so the server rejects every request with a 400.This looks like a regression of the older #8325 (closed, fixed for a different endpoint/cause) — same user-visible symptom, different root cause.
Environment
opencode web, behind an nginx reverse proxy on a custom domain)localhost0.0.0.0/browsing from a multi-project rootRoot cause
The server's own OpenAPI schema for
GET /filemarkspathas required:{ "name": "path", "in": "query", "schema": { "type": "string" }, "required": true }Confirmed directly against a running server:
Server log confirms the rejection:
But the frontend's directory-picker code calls the SDK's
file.list()without apathfield, in both the v1 and v2 directory pickers:packages/app/src/components/directory-picker-domain.ts(~line 345):packages/app/src/components/dialog-select-directory-v2.tsx(~line 130):Meanwhile, the SDK's own generated types (
packages/sdk/js/src/v2/gen/types.gen.ts) show the correct/expected shape:So the call sites use an outdated
{ location: { directory } }shape instead of the flat{ directory, path }shape the SDK types (and server) now require. Because the.catch(() => [])swallows the resulting 400 error, the UI shows an empty "No folders found" state with no visible error at all, making this very hard to diagnose from the UI alone.Steps to reproduce
opencode webwith a specific project directory (not the filesystem root/home), behind a reverse proxy on a non-localhostdomain.GET /file?...(or/find/file?...) requests returning400 Bad Requestwith{"message":"Missing key\n at [\"path\"]"}.Expected behavior
The directory picker should list real folders, since the underlying REST API works correctly when called with the required
pathparameter.Suggested fix
Update the call sites in
directory-picker-domain.tsanddialog-select-directory-v2.tsxto include an explicitpath: ""(or the correct relative path being browsed) alongsidedirectory, matching theFileListDataquery shape. Also consider not silently swallowing HTTP errors in.catch(() => [])for this codepath, so future contract mismatches surface as a visible error rather than a confusing empty state.