wavetermdev/waveterm · error

cannot expand wsh path: %w

Error message

cannot expand wsh path: %w

What it means

getWshPath failed expanding '~/.waveterm/bin/wsh' via wavebase.ExpandHomeDir for a remote server, meaning the user's home directory could not be resolved on the remote host. Used by RemoteStartJobCommand to locate the remote wsh binary.

Source

Thrown at pkg/wshrpc/wshremote/wshremote.go:136

	if err := os.MkdirAll(symlinkDir, 0700); err != nil {
		return fmt.Errorf("could not create client directory %s: %w", symlinkDir, err)
	}
	os.Remove(symlinkPath)
	if err := os.Symlink(impl.SockName, symlinkPath); err != nil {
		return fmt.Errorf("could not create symlink %s -> %s: %w", symlinkPath, impl.SockName, err)
	}
	impl.Log("created symlink %s -> %s\n", symlinkPath, impl.SockName)
	return nil
}

func (impl *ServerImpl) getWshPath() (string, error) {
	if impl.IsLocal {
		return filepath.Join(wavebase.GetWaveDataDir(), "bin", "wsh"), nil
	}
	wshPath, err := wavebase.ExpandHomeDir("~/.waveterm/bin/wsh")
	if err != nil {
		return "", fmt.Errorf("cannot expand wsh path: %w", err)
	}
	return wshPath, nil
}

func (impl *ServerImpl) BadgeWatchPidCommand(ctx context.Context, data wshrpc.CommandBadgeWatchPidData) error {
	if data.Pid <= 0 {
		return fmt.Errorf("invalid pid: %d", data.Pid)
	}
	if data.ORef.IsEmpty() {
		return fmt.Errorf("oref is required")
	}
	if data.BadgeId == "" {
		return fmt.Errorf("badgeid is required")
	}
	go func() {
		defer func() {
			panichandler.PanicHandler("BadgeWatchPidCommand", recover())
		}()

View on GitHub (pinned to a4447c1563)

Solutions

  1. Ensure HOME is set for the SSH user on the remote host
  2. Use a normal shell account rather than a chrooted/restricted one
  3. Verify wavebase.ExpandHomeDir behavior for the target platform
  4. Note: only non-local servers hit this path; local builds return the data dir directly
Defensive patterns

Strategy: validation

Validate before calling

out, err := runOnRemote("echo $HOME")
if err != nil || strings.TrimSpace(out) == "" {
    return fmt.Errorf("remote HOME not set; cannot resolve wsh path")
}

Try / catch

path, err := impl.getWshPath()
if err != nil {
    return fmt.Errorf("remote wsh unavailable (check HOME on remote): %w", err)
}

Prevention

When it happens

Trigger: Calling RemoteStartJobCommand on a remote connection where ExpandHomeDir('~/.waveterm/bin/wsh') errors — HOME unset or unparseable for the SSH user.

Common situations: SSH into accounts with no/odd HOME env (restricted shells, nologin users), sftp-only chrooted accounts, Windows remote without proper HOME mapping.

Related errors


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