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

  1. Reconnect the distro first: call conn.Connect(ctx) or conn.Reconnect(ctx), then retry UpdateWsh
  2. Wait for readiness with conn.WaitForConnect(ctx) before issuing the update
  3. 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

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


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/166e7b55a1e525ca. Report an issue: GitHub.