Skip to content

Coverage decorations not applied when working directory contains symlinks (sshfs/nfs mounts) #3938

@schmidtw

Description

@schmidtw

What version of Go, VS Code & VS Code Go extension are you using?

Version Information
* Run `go version` to get version of Go from _the VS Code integrated terminal_. - go version go1.25.5 linux/amd64 * Run `gopls -v version` to get version of Gopls from _the VS Code integrated terminal_. ``` Build info ---------- golang.org/x/tools/gopls v0.20.0 golang.org/x/tools/[email protected] h1:fxOYZXKl6IsOTKIh6IgjDbIDHlr5btOtOUkrGOgFDB4= github.com/BurntSushi/[email protected] h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/fatih/[email protected] h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/[email protected] h1:dDSgAjoOMp8da3egfz0t2S+t8RGOpEmEXZubcGuc0Bg= github.com/fatih/[email protected] h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fsnotify/[email protected] h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/google/[email protected] h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= golang.org/x/exp/[email protected] h1:KdrhdYPDUvJTvrDK9gdjfFd6JTk8vA1WJoldYSi0kHo= golang.org/x/[email protected] h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= golang.org/x/[email protected] h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/[email protected] h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/[email protected] h1:DU+gwOBXU+6bO0sEyO7o/NeMlxZxCZEvI7v+J4a1zRQ= golang.org/x/[email protected] h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/[email protected] h1:ZRKyKRJl/YEWl9ScZwd6Ua6xSt7DE6tHp1I3ucMroGM= golang.org/x/[email protected] h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I= honnef.co/go/[email protected] h1:fj8r9irJSpolAGUdZBxJIRY3lLc4jH2Dt4lwnWyWwpw= mvdan.cc/[email protected] h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= mvdan.cc/xurls/[email protected] h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI= go: go1.25.2 ``` * Run `code -v` or `code-insiders -v` to get version of VS Code or VS Code Insiders. ``` 1.106.3 bf9252a2fb45be6893dd8870c0bf37e2e1766d61 x64 ``` * Check your installed extensions to get the version of the VS Code Go extension - 0.50.0 * Run Ctrl+Shift+P (Cmd+Shift+P on Mac OS) > `Go: Locate Configured Go Tools` command. - All tools located in standard GOPATH/bin

Share the Go related settings you have added/edited

{
  "go.coverOnSave": true,
  "go.coverageOptions": "showBothCoveredAndUncoveredCode"
}

Describe the bug

Code coverage decorations are not applied when the working directory path contains symlinks (common with sshfs or nfs mounts). Tests run successfully and generate coverage data, but the coverage highlights/gutters never appear in the editor.

Expected behavior: Coverage decorations should be displayed regardless of whether the project path contains symlinks.

Root cause: The applyCodeCoverage function in goCover.ts compares file paths from two different sources that resolve symlinks differently:

  1. editor.document.fileName - The path as VS Code sees it (may include symlinks)
  2. Coverage data keys - Paths resolved via go list -f {{.Dir}}

When VS Code internally resolves paths differently than go list, the string comparison fails and coverage is never applied.

Steps to reproduce the behavior:

  1. Create a symlink in your path, e.g., ln -s ~/work/actual ~/work/mylink
  2. Open a Go project through the symlinked path: code ~/work/mylink/myproject
  3. Run tests with coverage via Go: Toggle Test Coverage In Current Package
  4. Observe that coverage gutters/highlights do not appear despite successful test execution

Screenshots or recordings

Diagnostic evidence showing the path mismatch:

# Working directory (what VS Code sees)
$ pwd
/home/user/mnt/remote/work/oss/svelte/wrpslog

# Canonical path (symlinks resolved)
$ pwd -P
/home/user/mnt/remote/work/oss/wrpslog

# What go list returns (preserves symlinks)
$ go list -f '{{.Dir}}' .
/home/user/mnt/remote/work/oss/svelte/wrpslog

# What Node.js fs.realpathSync returns
$ node -e "console.log(require('fs').realpathSync('$(pwd)/file.go'))"
/home/user/mnt/remote/work/oss/wrpslog/file.go  # <-- resolved, doesn't match!

Proposed Fix

Normalize both paths using fs.realpathSync() before comparison in goCover.ts:

 export function applyCodeCoverage(editor: vscode.TextEditor | undefined) {
 	if (!editor || editor.document.languageId !== 'go' || editor.document.fileName.endsWith('_test.go')) {
 		return;
 	}
 	let doc = editor.document.fileName;
 	if (path.isAbsolute(doc)) {
 		doc = fixDriveCasingInWindows(doc);
+		try {
+			doc = fs.realpathSync(doc);
+		} catch {
+			// File might not exist, keep original path
+		}
 	}

 	const cfg = getGoConfig(editor.document.uri);
 	const coverageOptions = cfg['coverageOptions'];
 	for (const filename in coverageData) {
-		if (doc !== fixDriveCasingInWindows(filename)) {
+		let normalizedFilename = fixDriveCasingInWindows(filename);
+		try {
+			normalizedFilename = fs.realpathSync(normalizedFilename);
+		} catch {
+			// Keep original if resolution fails
+		}
+		if (doc !== normalizedFilename) {
 			continue;
 		}

Environment

  • OS: Linux (Fedora 42)
  • Filesystem: sshfs and nfs4 mounts with symlinks in path

Notes

Due to the Shai-Hulud 2 attacks, I'm not comfortable attempting to test this locally. I'm not an npm developer, but other alternative (launching in the directory without the symlink) works. I had help from AI debugging this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions