gopls version

Build info
----------
golang.org/x/tools/gopls v0.18.1
    golang.org/x/tools/gopls@v0.18.1 h1:2xJBNzdImS5u/kV/ZzqDLSvlBSeZX+pWY9uKVP7Pask=
    github.com/BurntSushi/toml@v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
    github.com/google/go-cmp@v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
    golang.org/x/exp/typeparams@v0.0.0-20241210194714-1829a127f884 h1:1xaZTydL5Gsg78QharTwKfA9FY9CZ1VQj6D/AZEvHR0=
    golang.org/x/mod@v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
    golang.org/x/sync@v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
    golang.org/x/telemetry@v0.0.0-20241220003058-cc96b6e0d3d9 h1:L2k9GUV2TpQKVRGMjN94qfUMgUwOFimSQ6gipyJIjKw=
    golang.org/x/text@v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
    golang.org/x/tools@v0.30.1-0.20250221230316-5055f70f240c h1:Ja/5gV5a9Vvho3p2NC/T2TtxhHjrWS/2DvCKMvA0a+Y=
    golang.org/x/vuln@v1.1.3 h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw=
    honnef.co/go/tools@v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=
    mvdan.cc/gofumpt@v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
    mvdan.cc/xurls/v2@v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
go: go1.24.4

go env

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

What did you do?

While writing some tests, my editor would periodically die (via OOM killer). It took a while to track down, but I can reproduce this on two separate machines. Here's how to trigger it:

package goplscrash_test

import "testing"

type TestSuite struct{}

func (ts *TestSuite) Test(t *testing.T) {
    t.Run("Foo", ts.TestFoo)
    // Type this line slowly. To actually trigger it, let your cursor rest
    // after you've typed 'Test'
    // t.Run("FooBar", ts.TestFooBar)
}

func (ts *TestSuite) TestFoo(t *testing.T)    {}
func (ts *TestSuite) TestFooBar(t *testing.T) {}

What did you see happen?

The gopls process consumed all memory on my system, which caused my editor to die. Looking at logs, it seems the issue occurs here:

goroutine 7822 [runnable]:
internal/bytealg.LastIndexByteString(...)
    /usr/lib/go/src/internal/bytealg/lastindexbyte_generic.go:18
strings.LastIndex({0xca3ac4e000?, 0x1ef5c6b2082cce28?}, {0x149ad30?, 0x49af8?})
    /usr/lib/go/src/strings/strings.go:88 +0x2b2
golang.org/x/tools/gopls/internal/cache/testfuncs.parseSubtestNumber({0xca3ac4e000, 0x49af8})
    /home/shane/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/cache/testfuncs/match.go:55 +0x2d
golang.org/x/tools/gopls/internal/cache/testfuncs.(*indexBuilder).uniqueName(0xc4f1101b98, {0xca3abbe000?, 0xc00aa3ec40?}, {0xc008d9c528?, 0x3})
    /home/shane/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/cache/testfuncs/match.go:30 +0xea
golang.org/x/tools/gopls/internal/cache/testfuncs.(*indexBuilder).findSubtests(0xc4f1101b98, {{{0xc008d8dd60, 0x39}, {{0xb, 0x1}, {0xb, 0x16}}}, {0xca3abbe000, 0x49af4}}, 0xc00aa3ed60, ...)
    /home/shane/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/cache/testfuncs/tests.go:166 +0x565
golang.org/x/tools/gopls/internal/cache/testfuncs.(*indexBuilder).findSubtests(0xc4f1101b98, {{{0xc008d8dd60, 0x39}, {{0xb, 0x1}, {0xb, 0x16}}}, {0xca3aa58000, 0x49af0}}, 0xc00aa3ed60, ...)
    /home/shane/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/cache/testfuncs/tests.go:172 +0x7d1
golang.org/x/tools/gopls/internal/cache/testfuncs.(*indexBuilder).findSubtests(0xc4f1101b98, {{{0xc008d8dd60, 0x39}, {{0xb, 0x1}, {0xb, 0x16}}}, {0xca3a938000, 0x49aec}}, 0xc00aa3ed60, ...)
    /home/shane/go/pkg/mod/golang.org/x/tools/gopls@v0.18.1/internal/cache/testfuncs/tests.go:172 +0x7d1
... keeps repeating after this point ...

I've captured a video that shows the runaway memory consumption caused by/during the infinite loop:

https://github.com/user-attachments/assets/381065ac-fd9e-4d0a-837a-4fc59f927ee6

What did you expect to see?

I didn't expect an infinite loop here.

Editor and settings

Editor: VSCode

$ code --version --verbose
1.100.3
258e40fedc6cb8edf399a463ce3a9d32e7e1f6f3
x64

Go-specific settings in use (settings.json)

{
// ...
    "go.coverOnSingleTest": true,
    "go.coverOnSingleTestFile": true,
    "go.formatTool": "gofumpt",
    "go.survey.prompt": false,
    "go.testFlags": [
        "-v",
        "-count=1"
    ],
    "go.toolsGopath": "/home/shane/.local/lib/vscode-go",
// ...
}

Logs

I collected these from the web interface while gopls was in the process of eating all my memory. Apologies if these aren't in the expected format, but they more than narrow down where the issue occurs.

metrics.log heap.log goroutine_debug2.log goroutine_debug1.log allocs.log

Comment From: adonovan

Thanks for the exemplary bug report! This looks like a dup of https://github.com/golang/go/issues/72769, which was fixed in March. Can you go install golang.org/x/tools/gopls@v0.19.0-pre.3 and confirm that it fixes the problem for you? If not, please reopen the issue.

Comment From: gabyhelp

Related Issues

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Comment From: sbueschel

Thanks for the exemplary bug report! This looks like a dup of #72769, which was fixed in March. Can you go install golang.org/x/tools/gopls@v0.19.0-pre.3 and confirm that it fixes the problem for you? If not, please reopen the issue.

Totally fixes it, much appreciated!