golang / vscode-go

Go extension for Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=golang.Go
Other
3.85k stars 738 forks source link

debug: failed to launch with error "invalid debug configuration - cannot unmarshal ... into `env`" #2206

Open ssrlive opened 2 years ago

ssrlive commented 2 years ago

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.18.1 darwin/amd64 * Run `gopls -v version` to get version of Gopls from _the VS Code integrated terminal_. - * Run `code -v` or `code-insiders -v` to get version of VS Code or VS Code Insiders. - Version: 1.66.2 Commit: dfd34e8260c270da74b5c2d86d61aee4b6d56977 Date: 2022-04-11T07:49:20.994Z (1 wk ago) Electron: 17.2.0 Chromium: 98.0.4758.109 Node.js: 16.13.0 V8: 9.8.177.11-electron.0 OS: Darwin x64 21.4.0 * Check your installed extensions to get the version of the VS Code Go extension - * Run Ctrl+Shift+P (Cmd+Shift+P on Mac OS) > `Go: Locate Configured Go Tools` command. - go-outline gotests gomodifytags impl goplay dlv staticcheck gopls

Share the Go related settings you have added/edited

Run Preferences: Open Settings (JSON) command to open your settings.json file. Share all the settings with the go. or ["go"] or gopls prefixes.

Describe the bug

Can NOT debug. Always pop-up this dialog tell me that Failed to launch: invalid debug configuration - cannot unmarshal bool into "env" of type string.

and launch.json is here

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Package",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${fileDirname}"
        }
    ]
}

I have test the same steps on Linux and everything looks fine.

Screenshots or recordings

Screen Shot 2022-04-22 at 14 56 05

hyangah commented 2 years ago

@ssrlive can you enable logging and see if there is any boolean type value among the env property in the launch request the extension is sending to the debug adapter?

@suzmue @polinasok We've seen the extension was sending non-string type env vars to the debug adapter which expects map[string]*string for env. I can think of two options:

1) relax Delve's type requirement ---> maybe to map[string]interface{}, or 2) make the extension to check env var elements and stringify if necessary.

What do you prefer?

polinasok commented 2 years ago

@ssrlive To enable the logging, you can use "showLog" and "logOutput":"dap" attributes in your launch.json. It also helps to follow the template and share what you have in settings.json. For example, I can reproduce this issue withh the following in my settings.json

"go.toolsEnvVars": { "BOOL": false}

And this is what's logged:

2022-04-22T15:19:07-07:00 debug layer=dap [<- from client]{"seq":2,"type":"request","command":"launch","arguments":{"name":"Launch file","type":"go","request":"launch","mode":"debug",..."env":{"BOOL":false,"GOPATH":"/Users/polina/go"}...}}

@hyangah Yes, the extension doesn't require strings while dlv does. We likely wanted to be consistent with os.Setenv, which expects string values, when we set the vars.

polinasok commented 2 years ago

Thinking about this more. As per the OS convention, the final values for environment variables must be strings. If users read or set the values in their Go programs, they will deal with them as strings. So it is logical to expect our users to provide all string values in their json maps. Of course, one might argue that we might also want to allow scalars like ints or bools because when environment variables are set on the command line, users can omit the quotes for strings without spaces. But I am not convinced that this is worth the added complexity in either extension or delve code or documentation or error messages.

I think the current message coming from delve is pretty clear and the problem is that the user doesn't realize that the unspecified env in launch.json is populated behind the scenes from go.toolsEnvVars from settings.json. If we want to push error checking and optional stringification into delve, we must log these transformations. And if we do the massaging in the extension, it would still be useful to log which values came from settings.json vs launch.json vs some default for all attributes in the final debug configuration passed to delve. We run into confusion over these with users all the times. And this is yet another example.

So I propose that we:

  1. specify in the description of go.toolsEnvVars and env and envFile that variable values must be strings
  2. check that they are strings when reading these in the extension, so the error messages relate to the original source.
  3. optionally accept and stringify ints, bools, etc.
  4. log any transformations that form the final configuration, so users can still trace where accepted values were coming from if they run into surprises
ssrlive commented 2 years ago

my settings.json

{
    "cmake.configureOnOpen": true,
    "explorer.confirmDelete": false,
    "gopls": {
    "build.allowModfileModifications": false
    },
    "go.toolsEnvVars": {

    "go.useGoProxyToCheckForToolUpdates":true
    },
    "go.terminal.activateEnvironment": true,
    "go.toolsGopath": ""
}
polinasok commented 2 years ago

my settings.json


{
    "cmake.configureOnOpen": true,
    "explorer.confirmDelete": false,
    "gopls": {
    "build.allowModfileModifications": false
    },
    "go.toolsEnvVars": {

    "go.useGoProxyToCheckForToolUpdates":true

This boolean true is getting rejected because we expect a string. But is this actually an env variable or an extension setting? I suspect you meant the latter and in that case it should be moved outside of "go.toolsEnvVars" at the same level as other "go.xxx" settings (hover for description once you do that).

},
"go.terminal.activateEnvironment": true,
"go.toolsGopath": ""

}

polinasok commented 2 years ago

@hyangah Is it even right that we pass go.toolsEnvVars intended for Go tools to debuggee? Probably not something we can challenge now as people configurations will break, but definitely something to clarify in the documentation. We have so many ways to set these (go.toolsEnvVars, go.testEnvFile, envFile, env). No wonder users are confused what takes precedence and set to what when (e.g. #452, #2128).

ssrlive commented 2 years ago
Starting: /Users/myname/go/bin/dlv dap --check-go-version=false --log=true --log-output=dap --listen=127.0.0.1:54604 --log-dest=3 from /Volumes/mydisk/myapp
DAP server listening at: 127.0.0.1:54604
2022-04-24T11:20:31+08:00 debug layer=dap DAP server pid = 9119
2022-04-24T11:20:31+08:00 debug layer=dap DAP connection 1 started
2022-04-24T11:20:31+08:00 debug layer=dap [<- from client]{"seq":1,"type":"request","command":"initialize","arguments":{"clientID":"vscode","clientName":"Visual Studio Code","adapterID":"go","locale":"en-us","linesStartAt1":true,"columnsStartAt1":true,"pathFormat":"path","supportsVariableType":true,"supportsVariablePaging":true,"supportsRunInTerminalRequest":true,"supportsMemoryReferences":true,"supportsProgressReporting":true,"supportsInvalidatedEvent":true}}
2022-04-24T11:20:31+08:00 debug layer=dap [-> to client]{"seq":0,"type":"response","request_seq":1,"success":true,"command":"initialize","body":{"supportsConfigurationDoneRequest":true,"supportsFunctionBreakpoints":true,"supportsConditionalBreakpoints":true,"supportsEvaluateForHovers":true,"supportsSetVariable":true,"supportsExceptionInfoRequest":true,"supportTerminateDebuggee":true,"supportsDelayedStackTraceLoading":true,"supportsLogPoints":true,"supportsDisassembleRequest":true,"supportsClipboardContext":true,"supportsSteppingGranularity":true,"supportsInstructionBreakpoints":true}}
2022-04-24T11:20:31+08:00 debug layer=dap [<- from client]{"seq":2,"type":"request","command":"launch","arguments":{"name":"Launch Package","type":"go","request":"launch","mode":"debug","showLog":true,"logOutput":"dap","program":".","__configurationTarget":5,"packagePathToGoModPathMap":{"/Volumes/mydisk/myapp":"/Volumes/mydisk/myapp"},"debugAdapter":"dlv-dap","showRegisters":false,"showGlobalVariables":false,"substitutePath":[],"dlvFlags":[],"hideSystemGoroutines":false,"dlvToolPath":"/Users/myname/go/bin/dlv","env":{"go.useGoProxyToCheckForToolUpdates":true,"GOPATH":"/Users/myname/go"},"__buildDir":"/Volumes/mydisk/myapp","__sessionId":"00cadb8a-6874-4e94-ab76-c7a3cd20f1a6"}}
2022-04-24T11:20:31+08:00 debug layer=dap Failed to launch: invalid debug configuration - cannot unmarshal bool into "env" of type string
2022-04-24T11:20:31+08:00 debug layer=dap [-> to client]{"seq":0,"type":"response","request_seq":2,"success":false,"command":"launch","message":"Failed to launch","body":{"error":{"id":3000,"format":"Failed to launch: invalid debug configuration - cannot unmarshal bool into \"env\" of type string","showUser":true}}}
hyangah commented 2 years ago

@ssrlive Your settings.json has syntax error.

"go.useGoProxyToCheckForToolUpdates": true shouldn't be an element of "go.toolsEnvVars".

This part

"go.toolsEnvVars": {

    "go.useGoProxyToCheckForToolUpdates":true
    },

should be

"go.toolsEnvVars": {
 },  /* or delete "go.toolsEnvVars" setting*/       
 "go.useGoProxyToCheckForToolUpdates":true,
ssrlive commented 2 years ago

I don't know, it generate automatically.

hyangah commented 2 years ago

The only setting the extension may automatically added is "go.useGoProxyToCheckForToolUpdates": true Since other settings require manual edits, I guess some race occurred while the extension added the setting. 🤷🏽‍♀️ But, correcting the settings error will fix the issue.

Looked through your settings.json, it looks like most settings can be deleted.

{
    "cmake.configureOnOpen": true,
    "explorer.confirmDelete": false,
}
gopherbot commented 2 years ago

Change https://go.dev/cl/401974 mentions this issue: package.json: clarify format and precedence of env-setting debug attributes

hyangah commented 2 years ago

@polinasok

@hyangah Is it even right that we pass go.toolsEnvVars intended for Go tools to debuggee?

Good point. Since now dlv can process env and the extension directly controls how to start dlv command (in the legacy debug adapter, env is the only way), we can take advantage of it in a more clean way.

1) update the debug configuration provider and the debug adapter factory to implement:

If debugAdapter == dlv-dap: launch dlv dap with the toolsEnvVars.

2) specify element types for "env" (https://github.com/golang/vscode-go/blob/27e8258de8d3b5d863e9ba84a0e9b8a8bd7e1b5f/package.json#L670)

polinasok commented 2 years ago
  1. update the debug configuration provider and the debug adapter factory to implement:

If debugAdapter == dlv-dap: launch dlv dap with the toolsEnvVars. - handle console=integratedTerminal/externalTerminal case accordingly. pass env verbatim (or env + envFile contents).

Start dlv with the env settings and let it decide how to combine that with env for debuggee? Makes sense.

  1. specify element types for "env" (https://github.com/golang/vscode-go/blob/27e8258de8d3b5d863e9ba84a0e9b8a8bd7e1b5f/package.json#L670 )

I didn't know how to do this when I updated the comments because typed properties are named. But now I think I found aa way: http://json-schema.org/understanding-json-schema/reference/object.html#pattern-properties

ssrlive commented 2 years ago

It looks no one can resolve this bug. this bug will live forever.

pjkaufman commented 2 years ago

Thanks to the discussion here, I was able to fix my issue with using the latest version of vscode-go. But is there a reason why the following settings.json caused issues?

{
    "go.toolsManagement.autoUpdate": true,
    "go.toolsEnvVars": {
        "gopls.env": { /* This caused an error message very similar to the above one except about objects*/
            "GOFLAGS": "-tags=integration unit"
        },
    },
    "go.buildTags": "-tags=integration unit",
    "diffEditor.wordWrap": "on",
    "editor.wordWrap": "on",
    "security.workspace.trust.untrustedFiles": "open",
    "window.zoomLevel": 1
}

Commenting out/removing go.toolsEnvVars fixed the problem.

hyangah commented 2 years ago
    "go.toolsEnvVars": {
        "gopls.env": { /* This caused an error message very similar to the above one except about objects*/
            "GOFLAGS": "-tags=integration unit"
        },
    },

"go.toolsEnvVars" expects string type key/value. I think this is a malformed setting btw.

pjkaufman commented 2 years ago
    "go.toolsEnvVars": {
        "gopls.env": { /* This caused an error message very similar to the above one except about objects*/
            "GOFLAGS": "-tags=integration unit"
        },
    },

"go.toolsEnvVars" expects string type key/value. I think this is a malformed setting btw.

Gotcha. It seems that this was either added a ways back by me before it rejected non-string type key value pairs or it was automatically added when I updated a setting. But now that I have removed it, it is working again.

MollyBa commented 3 days ago

请问现在有解决的办法了吗? 深受其害, 印象里 好像之前是可以的, 而且我直接运行是可以的, 唯有debug的时候报这个错误