[VS Code] Chat creation fails with "AbsolutePathBuf deserialized without a base path" when any workspace folder is virtual (non-`file` scheme) - uri.fsPath read without a scheme check

Open 💬 1 comment Opened Aug 3, 2026 by RobinLin666

What version of the IDE extension are you using?

26.721.41059 (win32-x64). Also reproduces on 26.721.30844.

What subscription do you have?

API key / pay-as-you-go.

Which IDE are you using?

VS Code 1.131.0 (commit e4c7e7b1d6d060162f4aa7f8225271b67ce1df75, x64)

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

What issue are you seeing?

Creating a new chat fails with:

Error creating chat
Invalid request: AbsolutePathBuf deserialized without a base path

whenever the VS Code window contains any workspace folder whose URI scheme is not file — i.e. a folder backed by a FileSystemProvider ([virtual workspace](<https://code.visualstudio.com/api/extension-guides/virtual-workspaces>)). It fails even when another, perfectly valid on-disk folder is also open.

Root cause: uri.fsPath is read without checking uri.scheme.

From the shipped bundle out/extension.js (26.721.41059):

function Xv(){let t=KSe.workspace.workspaceFolders?.map(r=>r.uri.fsPath)??[];return vr()?t.map(kr):t}

(identical code in 26.721.30844, minified as Qv). This feeds the active-workspace-roots and workspace-root-options handlers, which become { cwd: rootPaths[0], workspaceRoots: rootPaths }.

For a non-file scheme, Uri.fsPath does not return an absolute path. VS Code's URI._makeFsPath only applies the UNC/authority branch when scheme === 'file', so a virtual folder yields a drive-less, root-relative string:

<!-- linear:table-colwidths:266,266,266 -->
| workspace folder URI | uri.fsPath on Windows | absolute? |
| -- | -- | -- |
| vscode-vfs://github/microsoft/vscode | \microsoft\vscode | ❌ |
| myfs:/Root | \Root | ❌ |
| myfs-agent:/c%3A/Users/me/anchor (passthrough provider) | c:\Users\me\anchor | ✅ |
| file:///c:/Users/me/project | c:\Users\me\project | ✅ |

That non-absolute string is then sent as a workspace root, and the Rust core's AbsolutePathBuf deserializer rejects it. Because the failure happens while deserializing the whole request, it is all-or-nothing: one bad root kills chat creation instead of that root being skipped.

In my original case the workspace had two folders — the first one a real on-disk directory (valid c:\... path), the second one virtual. Chat creation still failed, even though a usable root was present and first in the list.

What steps can reproduce the bug?

Reproducible with a public, Microsoft-published extension — no private code needed:

  1. Install [GitHub Repositories](<https://marketplace.visualstudio.com/items?itemName=GitHub.remotehub>) (GitHub.remotehub) — the extension used as the reference example in VS Code's own virtual-workspace docs.
  2. Run Open GitHub Repository… from the Command Palette and open any repository. The window now has a vscode-vfs://github/<owner>/<repo> folder.
  3. (Optional, to show it fails even with a valid root) File → Add Folder to Workspace… and add any normal on-disk folder, so folder\[0\] is a valid file: path.
  4. Open the Codex panel and send any prompt.

Result: Error creating chat — Invalid request: AbsolutePathBuf deserialized without a base path

The same happens for any .code-workspace that lists a folder with a custom scheme, e.g.:

{
  "folders": [
    { "name": "Local",   "uri": "file:///c%3A/Users/me/project" },
    { "name": "Virtual", "uri": "myfs:/Root" }
  ]
}

What is the expected behavior?

Roots that cannot be a native working directory should be dropped before the request is sent, so chat opens using whatever valid roots remain. If none remain, the existing "Add a project to use Codex" empty state is the right thing to show — not an internal deserialization error.

The predicate should be "is this a fully-qualified native path?", i.e. exactly the AbsolutePathBuf contract the core already requires — not a proxy for it. Two obvious-looking alternatives are both wrong:

<!-- linear:table-colwidths:200,200,200,200 -->
| candidate predicate | myfs-agent:/c%3A/… (passthrough onto a real dir) | myfs:/Root | verdict |
| -- | -- | -- | -- |
| uri.scheme === 'file' | ❌ dropped, though it is a perfectly good working dir | ✅ dropped | too strict |
| path.isAbsolute(p) | ✅ kept | ❌ kept — on Windows path.win32.isAbsolute('\\Root') is true | too loose |
| fully-qualified (drive-rooted or UNC) | ✅ kept | ✅ dropped | ✅ correct |

path.isAbsolute is worth calling out explicitly: on Windows it accepts drive-relative paths like \Root, so it would let the exact value that breaks AbsolutePathBuf straight through.

The scheme check is too strict because a FileSystemProvider may legitimately be a passthrough onto a real directory and deliberately shape its URI so that uri.fsPath yields a valid native path — precisely so that agents deriving a cwd from workspaceFolders[…].uri.fsPath keep working, while the window still counts as a virtual workspace (which ms-python.python and ms-python.vscode-pylance key their behaviour off). Filtering purely on scheme would break that arrangement and leave the extension with zero roots.

Suggested shape:

const isFullyQualified = p => /^[a-zA-Z]:[\\/]/.test(p) || p.startsWith('\\\\'); // POSIX: p.startsWith('/')

const roots = (vscode.workspace.workspaceFolders ?? [])
  .map(f => f.uri.fsPath)
  .filter(isFullyQualified);

Related VS Code guidance, which is why fsPath cannot be trusted unconditionally in the first place:

Never assume that the URI scheme is file. URI.fsPath can only be used when the URI scheme is file. — [https://code.visualstudio.com/api/extension-guides/virtual-workspaces](<https://code.visualstudio.com/api/extension-guides/virtual-workspaces>)

A note on the shape of the fix: simply taking workspaceFolders[0] as cwd without a scheme check is not a sufficient alternative. I checked a neighbouring extension that does exactly that (fs.realpathSync(folders.map(f => f.uri.fsPath)[0] || os.homedir()), no filter, no try/catch) and it merely fails differently: it happens to work when folder\[0\] is a real directory, but throws when the virtual folder comes first — on Windows fs.realpathSync("\\microsoft\\vscode") raises UNKNOWN, and fs.realpathSync("\\Root") raises ENOENT: lstat "C:\\Root". Ordering luck, not robustness. The scheme filter is what actually makes this correct in every ordering.

Worth stressing that the Codex variant is the harsher one: it fails even when a valid on-disk root is present and is first in the list, because the non-absolute entry breaks deserialization of the entire request rather than just that one root.

Additional information

  • Impact is not limited to one extension. Any FileSystemProvider puts the window in this state: GitHub Repositories / Remote Repositories (vscode-vfs:), Azure Repos, WSL-less remote browsers, and third-party providers. Users hit it as soon as one such folder is present.
  • capabilities.virtualWorkspaces is not declared in the extension's package.json. Per the docs, an extension that doesn't declare it is treated as supporting virtual workspaces, so VS Code happily activates Codex in precisely the configuration where it breaks. Alongside the scheme filter, declaring "supported": "limited" with a short description would set correct expectations.
  • The error message is opaque. AbsolutePathBuf deserialized without a base path gives no indication that a workspace folder is at fault. Including the offending path in the error would have saved a lot of debugging; this also seems to be the common thread across openai/codex#23209, openai/codex#23213, openai/codex#27567, openai/codex#31983 and openai/codex#32474.
  • Not a duplicate of openai/codex#23213 (fails in all workspaces, including plain file: ones) or openai/codex#16815 / openai/codex#29454 (WSL agent mode). Closest related: openai/codex#35260 and [#2909](<https://github.com/openai/codex/issues/2909>). openai/codex#5323 touched virtual workspace roots but from the search-scoping angle.
  • Side observation (from reading kr(), not verified — no WSL on this machine): in WSL mode the path converter's fallback maps \Root/Root, which is POSIX-absolute, so the same workspace may appear to work there. That would mask the missing scheme check rather than fix it.

View original on GitHub ↗

1 Comment

yzm1 · 12 days ago

Confirming this also reproduces in a plain VS Code Dev Containers setup (not just Codespaces/virtual-FS/Azure Repos) — worth noting since the root cause generalizes beyond those.

Repro environment:

  • VS Code Desktop connected to a container via the Dev Containers extension (ghcr.io/devcontainers/* features, python:3.12 base image).
  • Workspace opened as /workspaces/<repo> inside the container.
  • Codex chat creation fails immediately with Error creating chat / Invalid request: AbsolutePathBuf deserialized without a base path.
  • Same workspace opened locally (outside any container) works fine.

Diagnostics that rule out a network/auth cause (in case it helps triage — this presents identically to a connectivity failure but isn't one):

  • DNS/TLS to api.openai.com and chatgpt.com resolve correctly, valid certs, no proxy/MITM in the container.
  • chatgpt.com/backend-api/codex/responses responds normally (401 unauthenticated, i.e. reachable).
  • codex login --device-auth (CLI) completes the device-code handshake against auth.openai.com without issue.
  • A 35s SSE stream held open fine (rules out an idle-timeout/MTU issue on the container's network path).

Matches the diagnosis in this issue: when the extension host runs remotely (which is exactly what a Dev Container is), the workspace folder URI is vscode-remote://dev-container+…/workspaces/<repo> rather than file://…, and uri.fsPath is read without checking that scheme.

Workaround confirmed: running the standalone codex CLI in the container's integrated terminal (npm i -g @openai/codex) works fine — it resolves its own cwd directly rather than going through the extension's workspace-folder URI handling, so it never hits this code path. That's a viable stopgap for anyone hitting this in a Dev Container until the fix lands.