charmbracelet/crush · error
invalid lsp env: %w
Error message
invalid lsp env: %w
What it means
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.
Source
Thrown at internal/lsp/client.go:203
}
// 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),
},
},
}
powernapClient, err := powernap.NewClient(clientConfig)View on GitHub (pinned to 7944b8e522)
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.
Example fix
// before
env = { GOFLAGS = "${CUSTOM_GOFLAGS}" } // unset in CI
// after
env = { GOFLAGS = "-tags=integration" } Defensive patterns
Strategy: validation
Validate before calling
for k, v := range lspCfg.Env {
if strings.Contains(v, "${") {
expanded := os.ExpandEnv(v)
if strings.Contains(expanded, "${") {
return fmt.Errorf("env %s=%q has unresolvable expansion", k, v)
}
}
} Type guard
func validLSPEnv(env map[string]string) bool {
for _, v := range env {
if strings.Count(v, "${") != strings.Count(os.ExpandEnv(v), "${") {
return false
}
}
return true
} Try / catch
client, err := lsp.New(cfg)
if err != nil && strings.Contains(err.Error(), "invalid lsp env") {
slog.Error("LSP env resolution failed; verify referenced variables exist", "env", cfg.Env, "error", err)
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- env %s: %w
- failed to configure providers: %w
- invalid lsp command: %w
- invalid lsp args: %w
- task agent not configured
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/6c2ba3b46c9481ac.
Report an issue: GitHub.