{"record":{"id":"79fde55b9e151f79","repo":"charmbracelet/crush","slug":"invalid-lsp-args-w","errorCode":null,"errorMessage":"invalid lsp args: %w","messagePattern":"invalid lsp args: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lsp/client.go","lineNumber":198,"sourceCode":"\t\treturn err\n\tcase <-closeCtx.Done():\n\t\tc.client.Kill()\n\t\treturn closeCtx.Err()\n\t}\n}\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),","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/lsp/client.go#L180-L216","documentation":"After resolving the command, createPowernapClient resolves the server's argument list via c.config.ResolvedArgs(c.resolver). If any argument string contains an expansion the resolver cannot evaluate, the client construction is aborted with \"invalid lsp args\". This happens before any process is spawned, purely at config-resolution time.","triggerScenarios":"Calling New or Restart where config.ResolvedArgs(c.resolver) returns an error — e.g. args like [\"--config\", \"${PROJECT_SETTINGS}\"] with PROJECT_SETTINGS unset, or a malformed template in an arg.","commonSituations":"Args reference env/config variables missing in the launch environment; args copied from another tool's config that use a different variable syntax; args contain a typo in a template placeholder.","solutions":["Define every variable referenced in the lsp args in the environment or resolver config.","Replace templated args with literal values in the LSP configuration.","Fix placeholder syntax in args so it matches what the resolver supports.","Log/print ResolvedArgs output in isolation to identify which specific arg fails."],"exampleFix":"// before\nargs = [\"--remote\", \"${LSP_HOST}\"] // LSP_HOST unset\n\n// after\nargs = [\"--remote\", \"127.0.0.1:9000\"]","handlingStrategy":"validation","validationCode":"for _, a := range lspCfg.Args {\n    if strings.Contains(a, \"${\") && os.ExpandEnv(a) == a && strings.Contains(a, \"$\") {\n        return fmt.Errorf(\"arg %q contains unresolvable expansion\", a)\n    }\n}","typeGuard":"func validLSPArgs(args []string) bool {\n    for _, a := range args {\n        if strings.Contains(a, \"$ {\") || strings.Contains(a, \"${\") {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"client, err := lsp.New(cfg)\nif err != nil {\n    var target error\n    if errors.Unwrap(err) != nil {\n        slog.Error(\"LSP args failed to resolve; check placeholder syntax and env\", \"args\", cfg.Args, \"error\", err)\n    }\n    return err\n}","preventionTips":["Keep args literal where possible; only template what must vary per environment.","Log the resolved args once at startup to catch silent resolution drift.","Match placeholder syntax exactly to what the resolver documents."],"tags":["lsp","config","args-resolution"],"backgroundTag":"command-resolution-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}