Skip to content

x/tools/gopls: "Create variable" declares x := nil or x := 0 where the use needs another type #81808

Closed

Description

@wangzhihao-lab

gopls version

golang.org/x/tools/gopls v0.23.0 (h1:Dn6mf9WXu9iLnTftDDMb9wV0c6Se7PjzEMqP0LEe08Y=), built with go1.27.1.
v0.23.0 is still the newest gopls release (checked 2026-09-28); all five cases reproduce on it again in 3 of 3 runs.
Same results with gopls v0.20.0.

go env

GOARCH=arm64
GOOS=darwin
GOVERSION=go1.27.1
GOFLAGS=-modcacherw
GOTOOLCHAIN=local

(macOS 27 on Apple silicon; path variables left out.)

What did you do?

I drive gopls over LSP from a small script. In five public projects I misspelled one use of a name, which gives undefined: X (UndeclaredName), and applied the quick fix "Create variable X". Each file builds before the typo. Line numbers are 1-based.

  1. spf13/cobra at adbc8813901bba65827259daa8e22ff94ec1f30e, command_win.go (a Windows-only file; gopls reports it with [windows,amd64]), MousetrapHelpText misspelled on line 32:

    func preExecHook(c *Command) {
    	if MousetrapHelpText != "" && mousetrap.StartedByExplorer() {
    		c.Print(MousetrappHelpText)

    "Create variable MousetrappHelpText" inserts MousetrappHelpText := nil above line 32.

  2. XTLS/Xray-core at d562d8947d3175db86b4fa849742433a9876cb63, common/crypto/io.go, reader misspelled in a struct field of type io.Reader:

    func NewCryptionReader(stream cipher.Stream, reader io.Reader) *CryptionReader {
    	return &CryptionReader{
    		stream: stream,
    		reader: reaer,
    	}
    }

    "Create variable reaer" inserts reaer := 0 as the first line of the function.

  3. charmbracelet/bubbletea at 657aaae216e3f87df09b60959a9fe5de7b2ca419, examples/list-default/main.go (module examples), the type name model misspelled in a composite literal:

    	m := moddel{list: list.New(items, list.NewDefaultDelegate(), 0, 0)}

    "Create variable moddel" inserts moddel := 0 above it.

  4. caddyserver/caddy at c18099a0af5e88c8d9da0b9d797f6f2c62d60a23, modules/caddyhttp/reverseproxy/selectionpolicies_test.go line 126, poool[1].countRequest(1): the fix inserts poool := 0.

  5. nektos/act at 4f411281417e88660bea1c1a1749aa71ae0bd60f, pkg/container/docker_auth.go line 29, strings.ContainsAny(imge[:index], ".:"): the fix inserts imge := 0.

What did you see happen?

In every case the fix removes undefined: X and the file gets a different compile error instead (gopls publishes it right after the edit; the lines below are from go build, or go vet for the test file):

case inserted error after the fix
1 cobra (GOOS=windows GOARCH=amd64 go build .) MousetrappHelpText := nil ./command_win.go:32:25: use of untyped nil in assignment
2 Xray-core reaer := 0 common/crypto/io.go:19:11: cannot use reaer (variable of type int) as io.Reader value in struct literal: int does not implement io.Reader (missing method Read)
3 bubbletea moddel := 0 list-default/main.go:80:7: moddel (local variable) is not a type
4 caddy (go vet) poool := 0 modules/caddyhttp/reverseproxy/selectionpolicies_test.go:127:2: cannot index poool (variable of type int)
5 act imge := 0 pkg/container/docker_auth.go:30:40: cannot slice imge (variable of type int)

Each case reproduced in 3 of 3 runs.

What did you expect to see?

The docs say the fix inserts "a declaration with a default value inferring its type from the context". So:

  • case 1: Print is declared as Print(i ...interface{}), so the context type is interface{}, and x := nil never compiles; something like var MousetrappHelpText interface{} would.
  • case 2: the context type is io.Reader (the struct field), so var reaer io.Reader.
  • case 3: the name is used as a type, so no variable can fix it; I expected no "Create variable" action there.
  • cases 4 and 5: I don't know what type could be inferred, but := 0 cannot be indexed or sliced, so the fix only trades one error for another.

Editor and settings

No editor; a script over stdio (gopls serve). Settings returned for workspace/configuration: {"semanticTokens": true, "hints": {"assignVariableTypes": true, "compositeLiteralFields": true, "compositeLiteralTypes": true, "constantValues": true, "functionTypeParameters": true, "parameterNames": true, "rangeVariableTypes": true}}.

Logs

LSP trace (case 1)

F stands for the URI of command_win.go; positions are 0-based.

--> textDocument/didChange {"textDocument":{"uri":F,"version":2},"contentChanges":[{"range":{"start":{"line":31,"character":10},"end":{"line":31,"character":27}},"text":"MousetrappHelpText"}]}
<-- textDocument/publishDiagnostics {"uri":F,"version":2,"diagnostics":[{"range":{"start":{"line":31,"character":10},"end":{"line":31,"character":28}},"severity":1,"code":"UndeclaredName","source":"compiler","message":"undefined: MousetrappHelpText [windows,amd64]"}]}
--> textDocument/codeAction {"textDocument":{"uri":F},"range":{"start":{"line":31,"character":10},"end":{"line":31,"character":28}},"context":{"diagnostics":[(the diagnostic above)],"only":["quickfix"],"triggerKind":1}}
<-- [{"title":"Create variable MousetrappHelpText","kind":"quickfix","data":{"title":"Create variable MousetrappHelpText","command":"gopls.apply_fix",
      "arguments":[{"Fix":"create_undeclared","Location":{"uri":F,"range":{"start":{"line":31,"character":10},"end":{"line":31,"character":28}}},"ResolveEdits":true}]}}]
--> codeAction/resolve (that action)
<-- {"title":"Create variable MousetrappHelpText","kind":"quickfix","edit":{"documentChanges":[{"textDocument":{"version":2,"uri":F},
      "edits":[{"range":{"start":{"line":31,"character":2},"end":{"line":31,"character":2}},"newText":"MousetrappHelpText := nil\n\t\t"}]}]}}
--> textDocument/didChange (the edit above, version 3)
<-- textDocument/publishDiagnostics {"uri":F,"version":3,"diagnostics":[{"range":{"start":{"line":31,"character":24},"end":{"line":31,"character":27}},"severity":1,"code":"UntypedNilUse","source":"compiler","message":"use of untyped nil in assignment [windows,amd64]"}]}

Activity

  1. added
    ToolsThis label describes issues relating to any tools in the x/tools repository.
    goplsIssues related to the Go language server, gopls.
    on Sep 28, 2026
  2. added this to the Unreleased milestone on Sep 28, 2026
  3. wangzhihao-lab commented on Sep 28, 2026

    @wangzhihao-lab
    Author

    Case 3 (the misspelled type name in the composite literal, moddel{...}) is the case reported in #69947. The other four cases are about the inserted zero value (nil, 0) not matching the type the use needs.

  4. gopherbot commented on Oct 1, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/842926 mentions this issue: gopls/internal/golang: test Create variable in bad contexts

  5. gopherbot commented on Oct 5, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/845405 mentions this issue: gopls/internal/golang: replace assignment with declaration

  6. added a commit that references this issue on Oct 6, 2026
    d9d97d6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ToolsThis label describes issues relating to any tools in the x/tools repository.goplsIssues related to the Go language server, gopls.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions