charmbracelet/crush · error

invalid lsp args: %w

Error message

invalid lsp args: %w

What it means

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.

Source

Thrown at internal/lsp/client.go:198

		return err
	case <-closeCtx.Done():
		c.client.Kill()
		return closeCtx.Err()
	}
}

// createPowernapClient creates a new powernap client with the current configuration.
func (c *Client) createPowernapClient() error {
	rootURI := string(protocol.URIFromPath(c.cwd))

	command, err := c.resolver.ResolveValue(c.config.Command)
	if err != nil {
		return fmt.Errorf("invalid lsp command: %w", err)
	}

	args, err := c.config.ResolvedArgs(c.resolver)
	if err != nil {
		return fmt.Errorf("invalid lsp args: %w", err)
	}

	envs, err := c.config.ResolvedEnv(c.resolver)
	if err != nil {
		return fmt.Errorf("invalid lsp env: %w", err)
	}

	clientConfig := powernap.ClientConfig{
		Command:     home.Long(command),
		Args:        args,
		RootURI:     rootURI,
		Environment: envs,
		Settings:    c.config.Options,
		InitOptions: c.config.InitOptions,
		WorkspaceFolders: []protocol.WorkspaceFolder{
			{
				URI:  rootURI,
				Name: filepath.Base(c.cwd),

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Define every variable referenced in the lsp args in the environment or resolver config.
  2. Replace templated args with literal values in the LSP configuration.
  3. Fix placeholder syntax in args so it matches what the resolver supports.
  4. Log/print ResolvedArgs output in isolation to identify which specific arg fails.

Example fix

// before
args = ["--remote", "${LSP_HOST}"] // LSP_HOST unset

// after
args = ["--remote", "127.0.0.1:9000"]
Defensive patterns

Strategy: validation

Validate before calling

for _, a := range lspCfg.Args {
    if strings.Contains(a, "${") && os.ExpandEnv(a) == a && strings.Contains(a, "$") {
        return fmt.Errorf("arg %q contains unresolvable expansion", a)
    }
}

Type guard

func validLSPArgs(args []string) bool {
    for _, a := range args {
        if strings.Contains(a, "$ {") || strings.Contains(a, "${") {
            return false
        }
    }
    return true
}

Try / catch

client, err := lsp.New(cfg)
if err != nil {
    var target error
    if errors.Unwrap(err) != nil {
        slog.Error("LSP args failed to resolve; check placeholder syntax and env", "args", cfg.Args, "error", err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/79fde55b9e151f79. Report an issue: GitHub.