Skip to content

Sessions missing from sidebar on Windows due to path separator mismatch #23864

Closed

Description

@Gitar101

Description

On Windows, sessions created by sub-agent tools (like the Task/invoke developer agent tool) do not appear in the web UI sidebar. The sidebar shows the project tile but lists zero sessions. The sessions are still accessible via direct URL.

Steps to Reproduce

  1. Run opencode serve on Windows
  2. Use a sub-agent tool that creates a child session
  3. Observe the sidebar: the project tile appears but lists zero sessions
  4. Navigate directly to the session URL: the session loads and works fine

Root Cause

The child store system uses raw directory strings as keys for Maps and Records. On Windows, the same directory path can arrive in two formats:

  • C:\Users\user\Desktop\project (backslashes, from server-sent events)
  • C:/Users/user/Desktop/project (forward slashes, from URL decoding)

These are the same logical path but different JavaScript string keys. The child store creates two separate entries. The sidebar reads from one key while the event handler writes to the other, so sessions vanish from the sidebar.

There are also two related bugs:

  1. loadSessions() uses globalSDK.client.session.list() instead of sdkFor(directory).session.list(), so the server defaults to process.cwd() instead of the requested project directory
  2. The path getter in child-store.ts returns directory: "" in its fallback case, causing isRootVisibleSession() comparisons to always fail

Environment

  • Windows 11
  • OpenCode serve mode (web UI)
  • Any browser

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 22, 2026
  2. github-actions commented on Apr 22, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is distinct (e.g. specifically about child/sub-agent sessions or the loadSessions() SDK targeting bug), please add a note clarifying what distinguishes it from the above.

  3. liujieji commented on Apr 24, 2026

    @liujieji

    Same issue here on Windows with OpenCode v1.14.24. The sidebar fails to show historical sessions for the same project — likely the same path separator mismatch problem. Can confirm this bug is still present in the latest version.

  4. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  5. duyiliu commented on May 9, 2026

    @duyiliu

    I can confirm this still reproduces on Windows with OpenCode 1.14.41.

    Environment:

    • OS: Windows 11
    • OpenCode: opencode-ai 1.14.41
    • Mode: opencode serve / opencode web
    • Browser access through localhost

    Local evidence from the same machine:

    project.worktree = C:\Users\zhangqianfeng\playground
    session.directory = C:\Users\zhangqianfeng\playground
    root sessions for that directory = 9
    

    The server API behaves differently only based on slash style:

    GET /session?directory=C%3A%5CUsers%5Czhangqianfeng%5Cplayground&roots=true&limit=55
    => returns 9 sessions
    
    GET /session?directory=C%3A%2FUsers%2Fzhangqianfeng%2Fplayground&roots=true&limit=55
    => returns 0 sessions
    

    So the data is present and the issue is still an exact-match path separator mismatch.

    One important detail: PR #23862 normalizes client-side map/cache keys and says it does not change the raw directory value passed to API calls. That may not fully fix this direct API failure, because /session?directory=C:/Users/... still misses rows stored as C:\Users\....

    A robust fix may also be needed server-side in session listing, for example by accepting equivalent Windows directory variants when filtering SessionTable.directory:

    function windowsDirectoryVariants(directory: string) {
      if (!/^[a-zA-Z]:[\\/]/.test(directory) && !directory.startsWith("\\\\") && !directory.startsWith("//")) {
        return [directory]
      }
      return Array.from(new Set([directory, directory.replaceAll("/", "\\"), directory.replaceAll("\\", "/")]))
    }
    
    function directoryCondition(directory: string) {
      const variants = windowsDirectoryVariants(directory)
      if (variants.length === 1) return eq(SessionTable.directory, directory)
      return or(...variants.map((item) => eq(SessionTable.directory, item)))!
    }

    Then use that condition anywhere session listing currently does:

    eq(SessionTable.directory, input.directory)

    Affected places I found:

    • packages/opencode/src/session/session.ts
    • packages/opencode/src/v2/session.ts

    Temporary workaround that confirms the diagnosis: a local proxy that rewrites only query/header directory values from C:/Users/... to C:\Users\... makes the Web UI show the full session list again.

  6. duyiliu commented on May 9, 2026

    @duyiliu

    Follow-up with a more compact summary of the confirmed root cause and current local workaround.

    I think the important distinction is that Desktop showing ~\playground is only a display difference. The actual persisted records on Windows use the full backslash path:

    C:\Users\<user>\playground
    

    The Web UI, however, can request the same project as:

    C:/Users/<user>/playground
    

    When the session API filters by exact directory equality, those two strings do not match, so existing sessions are hidden even though they are still present in the database. In my local repro, querying the API with the backslash path returned the expected root sessions, while querying with the slash path returned none.

    The smallest safe local workaround I found was to keep the OpenCode Web backend on localhost and place a tiny local proxy in front of it that normalizes Windows directory query parameters before forwarding. That avoids editing or rewriting the OpenCode database.

    For future Windows reports, the repeatable diagnostic flow is:

    1. Check the stored project.worktree and session.directory values in the OpenCode database.
    2. Query the session API twice with the same project path, once as C:\... and once as C:/....
    3. If only the backslash form returns sessions, treat the database as intact and focus on server-side path normalization for the directory filter.
    4. Avoid rewriting the database as a workaround; a local path-normalizing proxy is safer until the upstream API behavior is fixed.

    The durable upstream fix still seems to be server-side normalization/equivalent matching for session/project directory filters, so API callers using either C:\... or C:/... resolve to the same project sessions.

  7. Hona commented on Jul 2, 2026

    @Hona
    Member

    Fixed in v1.16.0 by #29666.

    Path separators are now handled at the database boundary: session/project path columns are Drizzle custom types (packages/core/src/database/path.ts) that store forward slashes on Windows and normalize query parameters bound in eq(), so / and \ forms of the same path match the same rows. A one-time migration (20260601010001_normalize_storage_paths) rewrote existing backslash rows.

    Please upgrade to >= v1.16.0. If sessions are still missing from the sidebar on a current release, comment with opencode --version and a sample directory value from the session table and we will reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions