go: x/tools/gopls: single file erroneously full of "undeclared name: X" errors (and more!)

What version of Go are you using (go version)?

$ go version
go version go1.12.6 darwin/amd64

$ gopls version
golang.org/x/tools/gopls v0.1.2
    golang.org/x/tools/gopls@v0.1.3 h1:CB5ECiPysqZrwxcyRjN+exyZpY0gODTZvNiqQi3lpeo=

Does this issue reproduce with the latest release?

I believe so.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/peter/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/peter"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/Cellar/go/1.12.6/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.12.6/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/peter/mod/plasma/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/8s/kvkb2dzx37n057vk54y9b_ym0000gn/T/go-build417011332=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

I was working in a modules-based project, and reviewing an existing file, pkg/api/public.go. I created a new test file in the same package, contracts_test.go. I opened the file and wrote

package api

func TestContract_foo_BarBaz(t *testing.T) {

}

And saved the file. At some point between creating the new file and saving it, the public.go file I had been reading became full of red squiggles, each under a variety of identifiers for things defined in the same package, but another file, util.go: things like ErrFoo, or unexportedFunctions. Each of the errors suggested the identifier was not defined.

I ran gopls ... check on public.go at this point and got the following complete output: gist.

I opened the util.go file in the same package and confirmed the identifiers existed. When I went back to public.go, the red squiggles under the identifiers declared in the util.go file were gone, and now the only red squiggle was under an identifier for a type in another package, with the same error. Command-clicking on the identifier, however, brought me to the proper declaration in the other package.

Confused, I clicked back into public.go, and discovered: (a) the red squiggle under the identifier I had just clicked on was gone; (b) several other files in the same package which were not previously red (errored) had become red; and © there were several brand new red squiggles under all sorts of identifiers in public.go that had no common theme. For example, some code:

r := mux.NewRouter() // this is github.comgorilla/mux
// ...
s.Handler = r // s.Handler being of type http.Handler

had a red squiggle under r, the right hand side of the assignment, claiming “cannot use r (variable of type *mux.Router) as http.Handler value in assignment: wrong type for method ServeHTTP.”

At this point I ran gopls ... check on public.go again and got the following complete output: gist. (I think it is identical to before.)

I then captured the following output from gopls debug log in VS Code: gist.

I then decided I spent enough time whacking moles and ran pkill gopls. Within a second, all red files returned to their normal color, and all red squiggles went away.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 6
  • Comments: 22 (13 by maintainers)

Most upvoted comments

gopls … doesn’t yet watch changed files … so any time your file changes outside of the editor, the state of the cache will be incorrect.

Oh.

This is a key insight, and probably explains at least some of the frequency of my problems. I rarely do file manipulation (git branching, rebasing, file creation/deletion, structural re/organization) in the editor itself, rather through a separate terminal.

gopls is more likely to get confused when doing things like git rebasing, and it doesn’t yet watch changed files (though it will soon: https://go-review.googlesource.com/c/tools/+/190857), so any time your file changes outside of the editor, the state of the cache will be incorrect. To restart gopls, I’d suggest reloading the entire VSCode window (Developer: Reload Window), because I believe there are some issues with the restart command (https://github.com/microsoft/vscode-go/issues/2633).

We do see errors as we develop, but we can often attribute them to whatever we’re debugging at the moment. I have seen errors like the ones you describe randomly pop up, but they are infrequent enough (once a week or so), that I am surprised when you say that you see them very frequently. It’s very possible that @SteelPhase’s guess is correct - it’s probably more likely for things to get out of sync if you have a lot of dependencies.

@peterbourgon: Thank you for the screen-share offer. At this point, I think we have quite a few things that we’re working on to hopefully fix a number of these issues, but if you’re still seeing these errors after we submit all of our changes, I will take you up on that.

That is indeed a surprising bit of info. Is this documented anywhere? If gopls doesn’t handle files changing, then it’s not suitable for my use cases. This explains many of the issues I’ve been seeing. I’ve been following gopls development and I hadn’t understood this crucial point.

I’ve updated the Known Issues on the gopls wiki to indicate this. I’m sorry that we did not make this clear.

@SteelPhase: Thank you so much for investigating this and providing the repro case. We will take a look at it.