Skip to content

Launch config mode: auto infers test mode from active editor file, ignoring program field #3996

@firelizzard18

Description

@firelizzard18

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.3 X:nodwarf5 linux/amd64
  • Run gopls -v version to get version of Gopls from the VS Code integrated terminal.
    • golang.org/x/tools/gopls v0.21.1 go: go1.25.3 X:jsonv2
  • 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.53.1
  • Run Ctrl+Shift+P (Cmd+Shift+P on Mac OS) > Go: Locate Configured Go Tools command.

Tools Configuration

Environment

GOBIN: undefined
toolsGopath:
gopath: /home/firelizzard/go
GOROOT: /usr/lib/go
PATH: /usr/local/sbin:/usr/local/bin:/usr/bin:/opt/bin:/usr/lib/llvm/20/bin

Tools

go:	/usr/bin/go: go version go1.25.3 X:nodwarf5 linux/amd64

gotests:	/home/firelizzard/go/bin/gotests	(version: v1.6.0 built with go: go1.25.0)
impl:	/home/firelizzard/go/bin/impl	(version: v1.4.0 built with go: go1.25.0)
goplay:	/home/firelizzard/go/bin/goplay	(version: v1.0.0 built with go: go1.25.0)
dlv:	/home/firelizzard/go/bin/dlv	(version: v1.26.0 built with go: go1.25.3)
golint:	/home/firelizzard/go/bin/golint	(version: v0.0.0-20241112194109-818c5a804067 built with go: go1.25.0)
gopls:	/home/firelizzard/go/bin/gopls	(version: v0.21.1 built with go: go1.25.3)

Go env

Workspace Folder (vscode-go): /home/firelizzard/src/golang/vscode-go

AR='ar'
CC='x86_64-pc-linux-gnu-gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='x86_64-pc-linux-gnu-g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/firelizzard/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/firelizzard/.config/go/env'
GOEXE=''
GOEXPERIMENT='jsonv2'
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1554880090=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/firelizzard/src/golang/vscode-go/go.mod'
GOMODCACHE='/home/firelizzard/go/pkg/mod'
GONOPROXY='github.com/C3Rules/Go-DTRules'
GONOSUMDB='github.com/C3Rules/Go-DTRules'
GOOS='linux'
GOPATH='/home/firelizzard/go'
GOPRIVATE='github.com/C3Rules/Go-DTRules'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='on'
GOTELEMETRYDIR='/home/firelizzard/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.25.3 X:nodwarf5'
GOWORK=''
PKG_CONFIG='pkg-config'

Describe the bug

When a launch configuration has "mode": "auto" and "program" set to a directory, the extension infers whether to use debug or test mode by checking if the active editor's file ends with _test.go. The program field is ignored for this inference.

This means a named launch configuration targeting a specific directory will sometimes launch as a test binary and sometimes as a debug binary, depending on which file happens to be focused in the editor when the session starts — even if that file is in a completely unrelated package.

Expected behavior: When program is set to a directory, mode: auto should default to debug. The active editor file is irrelevant when an explicit target is specified.

Actual behavior: If any _test.go file is active in the editor, the extension sends mode: test to Delve regardless of the program field. If the target package has no test files, Delve produces an empty binary and the launch fails with not an executable file.

The offending code is here:

if (debugConfiguration['mode'] === 'auto') {
let filename = activeEditor?.document?.fileName;
if (debugConfiguration['program'] && debugConfiguration['program'].endsWith('.go')) {
// If the 'program' attribute is a file, not a directory, then we will determine the mode from that
// file path instead of the currently active file.
filename = debugConfiguration['program'];
}
debugConfiguration['mode'] = filename?.endsWith('_test.go') ? 'test' : 'debug';
}

The code only substitutes program for the active filename when program ends in .go. When program is a directory (the common case), the active editor file is used unconditionally.

I confirmed this by running the extension in extension host debug mode, observing the incorrect mode: test being sent to Delve, then making debugConfiguration['mode'] = 'debug' unconditional and confirming the issue was gone.

Steps to reproduce the behavior

  1. Create a launch configuration with "mode": "auto" and "program": "${workspaceFolder}" pointing at a package with no test files
  2. Open any _test.go file from another package in the editor so it is the active tab
  3. Run the launch configuration
  4. Observe that Delve receives mode: test, attempts to compile a test binary for the target package, produces an empty file, and fails with not an executable file

See also go-delve/delve#4229

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions