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
- 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.
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
- 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.
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
- env %s: %w
- invalid lsp command: %w
- invalid lsp env: %w
- task agent not configured
- small model provider not configured
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/79fde55b9e151f79.
Report an issue: GitHub.