charmbracelet/crush · error

failed to initialize the lsp client: %w

Error message

failed to initialize the lsp client: %w

What it means

The LSP client's Initialize method calls the underlying powernap client's Initialize (the LSP `initialize` handshake). If that request fails or the server errors/times out, this error wraps the cause. Handlers are registered before this call precisely so requests sent during initialization (e.g. workDoneProgress/create) are answered; failing means the server never completed the handshake.

Source

Thrown at internal/lsp/client.go:114

	if err := client.createPowernapClient(); err != nil {
		return nil, err
	}

	return client, nil
}

// Initialize initializes the LSP client and returns the server capabilities.
func (c *Client) Initialize(ctx context.Context, workspaceDir string) (*protocol.InitializeResult, error) {
	// Register handlers for requests the server may send during the
	// initialize handshake itself (e.g. typescript-language-server issuing
	// window/workDoneProgress/create while loading the project, before
	// initialize has returned). Registering after client.Initialize() is too
	// late for those — the server treats an unhandled response as fatal.
	c.registerHandlers()

	if err := c.client.Initialize(ctx, false); err != nil {
		return nil, fmt.Errorf("failed to initialize the lsp client: %w", err)
	}

	// Convert powernap capabilities to protocol capabilities
	caps := c.client.GetCapabilities()
	protocolCaps := protocol.ServerCapabilities{
		TextDocumentSync: caps.TextDocumentSync,
		CompletionProvider: func() *protocol.CompletionOptions {
			if caps.CompletionProvider != nil {
				return &protocol.CompletionOptions{
					TriggerCharacters:   caps.CompletionProvider.TriggerCharacters,
					AllCommitCharacters: caps.CompletionProvider.AllCommitCharacters,
					ResolveProvider:     caps.CompletionProvider.ResolveProvider,
				}
			}
			return nil
		}(),
	}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Check the wrapped error for the root cause (process not found, timeout, protocol error) and fix that first.
  2. Verify the LSP server command and args configured for the language are correct and the binary is installed/on PATH.
  3. Run the server manually with the same args to confirm it starts and speaks the expected protocol version.
  4. Increase the initialization timeout for slow-starting servers or large workspaces.
  5. Restart the LSP client (client.Restart) after fixing the server configuration.

Example fix

// before (crushrc)
lsp gopls "gopls" "wrong-flag"
// after
lsp gopls "gopls" "serve"
// ensure gopls is installed:
// go install golang.org/x/tools/gopls@latest
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the server binary is runnable before initializing
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := exec.CommandContext(ctx, cmd, args...).Run(); err != nil {
    return fmt.Errorf("LSP server %q is not runnable: %w", cmd, err)
}

Try / catch

client, err := lspClient.Initialize(ctx)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        return fmt.Errorf("LSP server did not respond in time; retry with a longer timeout")
    }
    return fmt.Errorf("LSP init failed, check server install/config: %w", err)
}

Prevention

When it happens

Trigger: Calling Initialize when the LSP server binary is missing or crashes at startup, the server sends an unhandled request/response during initialize, the connection drops, or the context deadline expires before the server responds.

Common situations: LSP binary not installed or not on PATH; misconfigured LSP command in crushrc (wrong args, wrong cwd); the server version doesn't match the expected protocol behavior; server crashed while loading a large project; timeout too short for slow startup.

Related errors


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