Skip to content

fix(terminal): catch ENOPRO in getCwdResource when file:// provider absent in VS Code web#317780

Open
mutl3y wants to merge 2 commits into
microsoft:mainfrom
mutl3y:fix/terminal-getcwdresource-web-enopro
Open

fix(terminal): catch ENOPRO in getCwdResource when file:// provider absent in VS Code web#317780
mutl3y wants to merge 2 commits into
microsoft:mainfrom
mutl3y:fix/terminal-getcwdresource-web-enopro

Conversation

@mutl3y
Copy link
Copy Markdown

@mutl3y mutl3y commented May 21, 2026

Problem

Fixes #317329 (related — same deployment scenario, different subsystem)

When using VS Code Server (server-linux-x64-web) accessed via a browser, calling getCwdResource() on a terminal instance throws:

Error: No file system provider found for resource 'file:///workspace' (ENOPRO)

This surfaces as a failure on every Copilot agent terminal tool invocation (the agent host calls getCwdResource() to resolve the working directory before running a shell command). Any other caller that relies on this method is similarly broken.

Root cause

getCwdResource() in terminalInstance.ts has two branches:

if (this.remoteAuthority) {
    resource = await this._pathService.fileURI(cwd);  // remote-aware ✅
} else {
    resource = URI.file(cwd);                          // Electron/desktop only ❌
}

In a self-hosted server-linux-x64-web deployment without an explicit remoteAuthority header, this.remoteAuthority is falsy from the terminal's perspective. The else branch fires, producing a file:///workspace URI. The browser FileService has no file:// provider registered — only the remote provider — so _fileService.exists(resource) throws ENOPRO.

This else branch is desktop/Electron-only code: in a correct remote-web context remoteAuthority would be set and _pathService.fileURI() would be used instead.

Fix

Wrap the function body in try/catch so that provider errors (ENOPRO or otherwise) return undefined, allowing callers to fall back to the default CWD rather than propagating the error. The existing logic is preserved — only the error path is changed.

async getCwdResource(): Promise<URI | undefined> {
    const cwd = this.capabilities.get(TerminalCapability.CwdDetection)?.getCwd();
    let resource: URI;
    try {
        if (this.remoteAuthority) {
            resource = await this._pathService.fileURI(cwd);
        } else {
            resource = URI.file(cwd);
        }
        if (await this._fileService.exists(resource)) { return resource; }
    } catch {
        // FileService provider not available for this URI scheme (e.g. file:// in
        // VS Code web where only the remote provider is registered).
        return undefined;
    }
    return undefined;
}

Testing

Verified against a running server-linux-x64-web instance (v1.121.0, commit f6cfa2ea) in a containerised deployment:

  • Before: Copilot agent terminal tool fails on every invocation with ENOPRO
  • After: Terminal tool executes successfully; getCwdResource returns undefined and the tool falls back to the default CWD

Notes

  • Only one file changed: src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
  • This is independent of PR Fix secret storage persistence in VS Code Server web #317333 (secret storage key minting) — different subsystem, different file
  • A more complete fix would detect the web context and always route through _pathService.fileURI(); this PR takes the minimal safe approach of catching the error

…bsent in VS Code web

In VS Code web (server-linux-x64-web accessed via browser), when remoteAuthority is
falsy from the terminal's perspective, getCwdResource() falls through to URI.file(cwd)
which produces a file:// URI. The browser FileService has no file:// provider
registered — only the remote provider — so _fileService.exists() throws ENOPRO
(No file system provider found for resource 'file:///...').

This causes the Copilot agent terminal tool (and any other caller of getCwdResource)
to fail on every invocation in self-hosted server-linux-x64-web deployments.

The fix wraps the function body in try/catch so that ENOPRO (or any provider error)
returns undefined, allowing callers to fall back to the default CWD gracefully.

The underlying issue is that the else branch (URI.file) is desktop/Electron-only code
that is unreachable in a correct web context: when remoteAuthority is properly set by
the server, _pathService.fileURI() is used instead. In server-linux-x64-web without
an explicit remoteAuthority header the else branch fires incorrectly.

Fixes: terminal getCwdResource ENOPRO in server-linux-x64-web / browser context
Copilot AI review requested due to automatic review settings May 21, 2026 14:32
@mutl3y mutl3y marked this pull request as ready for review May 21, 2026 14:37
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the terminal instance working-directory URI resolution in VS Code web/server scenarios by preventing getCwdResource() from throwing when the FileService cannot handle the produced URI (notably when a file:// provider is absent), allowing callers (including agent terminal tools) to fall back gracefully.

Changes:

  • Wrap TerminalInstance.getCwdResource() URI creation/existence validation in try/catch.
  • Return undefined instead of propagating provider-related errors (e.g. ENOPRO) from fileService.exists.

Comment on lines +2372 to 2391
try {
if (this.remoteAuthority) {
resource = await this._pathService.fileURI(cwd);
} else {
// Note: in VS Code web (server-linux-x64-web accessed via browser),
// remoteAuthority is falsy from the terminal's perspective, so URI.file()
// is used here. However, the browser FileService has no file:// provider
// registered, causing an ENOPRO error. We catch it so that callers receive
// undefined and fall back gracefully to the default CWD.
resource = URI.file(cwd);
}
if (await this._fileService.exists(resource)) {
return resource;
}
} catch {
// FileService provider not available for this URI scheme (e.g. file:// in
// VS Code web where only the remote provider is registered). Return undefined
// so callers fall back to the default CWD rather than propagating the error.
return undefined;
}
Comment on lines +2383 to +2390
if (await this._fileService.exists(resource)) {
return resource;
}
} catch {
// FileService provider not available for this URI scheme (e.g. file:// in
// VS Code web where only the remote provider is registered). Return undefined
// so callers fall back to the default CWD rather than propagating the error.
return undefined;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VS Code Server web: GitHub auth tokens lost on page refresh/folder switch (in-memory only)

3 participants