{"record":{"id":"6c2ba3b46c9481ac","repo":"charmbracelet/crush","slug":"invalid-lsp-env-w","errorCode":null,"errorMessage":"invalid lsp env: %w","messagePattern":"invalid lsp env: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lsp/client.go","lineNumber":203,"sourceCode":"}\n\n// createPowernapClient creates a new powernap client with the current configuration.\nfunc (c *Client) createPowernapClient() error {\n\trootURI := string(protocol.URIFromPath(c.cwd))\n\n\tcommand, err := c.resolver.ResolveValue(c.config.Command)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid lsp command: %w\", err)\n\t}\n\n\targs, err := c.config.ResolvedArgs(c.resolver)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid lsp args: %w\", err)\n\t}\n\n\tenvs, err := c.config.ResolvedEnv(c.resolver)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid lsp env: %w\", err)\n\t}\n\n\tclientConfig := powernap.ClientConfig{\n\t\tCommand:     home.Long(command),\n\t\tArgs:        args,\n\t\tRootURI:     rootURI,\n\t\tEnvironment: envs,\n\t\tSettings:    c.config.Options,\n\t\tInitOptions: c.config.InitOptions,\n\t\tWorkspaceFolders: []protocol.WorkspaceFolder{\n\t\t\t{\n\t\t\t\tURI:  rootURI,\n\t\t\t\tName: filepath.Base(c.cwd),\n\t\t\t},\n\t\t},\n\t}\n\n\tpowernapClient, err := powernap.NewClient(clientConfig)","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/lsp/client.go#L185-L221","documentation":"createPowernapClient resolves the environment map passed to the spawned LSP server via c.config.ResolvedEnv(c.resolver). If an environment entry's key or value contains an unresolvable expansion, construction fails with \"invalid lsp env\". This is the third of three config-resolution steps before the powernap client is built.","triggerScenarios":"Calling New or Restart where config.ResolvedEnv(c.resolver) errors — e.g. env entry \"GOPATH=${MY_GOPATH}\" with MY_GOPATH unset, or an invalid expansion expression inside an env value.","commonSituations":"LSP config sets custom env for the server using variables absent in the host environment (CI runners, cron, services with minimal env); malformed placeholder syntax in an env value.","solutions":["Export or define the variables referenced in the lsp env map before launching.","Remove or hardcode env entries that don't need templating.","Correct placeholder syntax in env keys/values to match resolver expectations.","Verify by echoing the variables in the same environment crush runs in."],"exampleFix":"// before\nenv = { GOFLAGS = \"${CUSTOM_GOFLAGS}\" } // unset in CI\n\n// after\nenv = { GOFLAGS = \"-tags=integration\" }","handlingStrategy":"validation","validationCode":"for k, v := range lspCfg.Env {\n    if strings.Contains(v, \"${\") {\n        expanded := os.ExpandEnv(v)\n        if strings.Contains(expanded, \"${\") {\n            return fmt.Errorf(\"env %s=%q has unresolvable expansion\", k, v)\n        }\n    }\n}","typeGuard":"func validLSPEnv(env map[string]string) bool {\n    for _, v := range env {\n        if strings.Count(v, \"${\") != strings.Count(os.ExpandEnv(v), \"${\") {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"client, err := lsp.New(cfg)\nif err != nil && strings.Contains(err.Error(), \"invalid lsp env\") {\n    slog.Error(\"LSP env resolution failed; verify referenced variables exist\", \"env\", cfg.Env, \"error\", err)\n    return err\n}","preventionTips":["Avoid templating env values that are constant; hardcode them.","Provide sane defaults with ${VAR:-default} style fallbacks where the resolver supports them.","Validate env resolution in CI with the same minimal env the runner uses."],"tags":["lsp","config","environment"],"backgroundTag":"env-var-resolution-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}