wavetermdev/waveterm · error
cannot update wsh: ssh client is not connected
Error message
cannot update wsh: ssh client is not connected
What it means
UpdateWsh needs the underlying *wsl.Distro client to copy the wsh binary into the distro. If conn.GetClient() returns nil, the SSH/WSL client handle has not been established (or was cleared on disconnect), so there is no channel through which to install the update and the call fails immediately before any copy is attempted.
Source
Thrown at pkg/wslconn/wslconn.go:369
type WshInstallOpts struct {
Force bool
NoUserPrompt bool
}
var queryTextTemplate = strings.TrimSpace(`
Wave requires Wave Shell Extensions to be
installed on %q
to ensure a seamless experience.
Would you like to install them?
`)
func (conn *WslConn) UpdateWsh(ctx context.Context, clientDisplayName string, remoteInfo *wshrpc.RemoteInfo) error {
conn.Infof(ctx, "attempting to update wsh for connection %s (os:%s arch:%s version:%s)\n",
conn.GetName(), remoteInfo.ClientOs, remoteInfo.ClientArch, remoteInfo.ClientVersion)
client := conn.GetClient()
if client == nil {
return fmt.Errorf("cannot update wsh: ssh client is not connected")
}
err := CpWshToRemote(ctx, client, remoteInfo.ClientOs, remoteInfo.ClientArch)
if err != nil {
return fmt.Errorf("error installing wsh to remote: %w", err)
}
conn.Infof(ctx, "successfully updated wsh on %s\n", conn.GetName())
return nil
}
// returns (allowed, error)
func (conn *WslConn) getPermissionToInstallWsh(ctx context.Context, clientDisplayName string) (bool, error) {
conn.Infof(ctx, "running getPermissionToInstallWsh...\n")
queryText := fmt.Sprintf(queryTextTemplate, clientDisplayName)
title := "Install Wave Shell Extensions"
request := &userinput.UserInputRequest{
ResponseType: "confirm",
QueryText: queryText,View on GitHub (pinned to a4447c1563)
Solutions
- Reconnect the distro first: call conn.Connect(ctx) or conn.Reconnect(ctx), then retry UpdateWsh
- Wait for readiness with conn.WaitForConnect(ctx) before issuing the update
- Check the connection status (conn.DeriveConnStatus) and only update when Status_Connected
Example fix
// before
err := conn.UpdateWsh(ctx, name, remoteInfo)
// after
if err := conn.WaitForConnect(ctx); err != nil {
return fmt.Errorf("connection not ready: %w", err)
}
err := conn.UpdateWsh(ctx, name, remoteInfo) Defensive patterns
Strategy: validation
Validate before calling
if conn.DeriveConnStatus().Status != Status_Connected {
return fmt.Errorf("cannot update wsh: connection %s is not connected", conn.GetName())
}
// safe to call UpdateWsh now Type guard
func wslClientReady(conn *wslconn.WslConn) bool {
return conn.DeriveConnStatus().Status == wslconn.Status_Connected
} Try / catch
if err := conn.UpdateWsh(ctx, name, remoteInfo); err != nil {
if strings.Contains(err.Error(), "ssh client is not connected") {
if cerr := conn.Connect(ctx); cerr == nil {
err = conn.UpdateWsh(ctx, name, remoteInfo)
}
}
} Prevention
- Always check DeriveConnStatus before mutating wsh on a connection
- Serialize update calls with connection lifecycle (no updates during reconnect)
- WaitForConnect before programmatic update jobs
When it happens
Trigger: Calling WslConn.UpdateWsh while the WSL distro is disconnected, before Connect() has completed, or after the connection was closed/reset so conn.Client is nil.
Common situations: Triggering a wsh update from the UI while the connection is in Status_Disconnected or Status_Init; a connection that dropped and its client was cleared, then an update job fires; calling UpdateWsh programmatically without first calling Connect/WaitForConnect.
Related errors
- ssh client is not connected, cannot install
- SwapToken is required in CommandOptsType
- unable to obtain client info: %w
- error checking wsh version: %w
- timeout waiting for connserver to register
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/166e7b55a1e525ca.
Report an issue: GitHub.