wavetermdev/waveterm · error

cannot open local file %s: %w

Error message

cannot open local file %s: %w

What it means

CpWshToRemote copies the locally installed wsh binary to a remote host. This error is wrapped when os.Open fails on the local wsh binary path computed by shellutil.GetLocalWshBinaryPath for the current Wave version and the detected client OS/arch. It means the binary to upload is missing or unreadable on the local machine, so the remote install cannot proceed.

Source

Thrown at pkg/remote/connutil.go:111

mkdir -p {{.installDir}} || exit 1;
cat > {{.tempPath}} || exit 1;
mv {{.tempPath}} {{.installPath}} || exit 1;
chmod a+x {{.installPath}} || exit 1;
`)
var installTemplate = template.Must(template.New("wsh-install-template").Parse(installTemplateRawDefault))

func CpWshToRemote(ctx context.Context, client *ssh.Client, clientOs string, clientArch string) error {
	deadline, ok := ctx.Deadline()
	if ok {
		blocklogger.Debugf(ctx, "[conndebug] CpWshToRemote, timeout: %v\n", time.Until(deadline))
	}
	wshLocalPath, err := shellutil.GetLocalWshBinaryPath(wavebase.WaveVersion, clientOs, clientArch)
	if err != nil {
		return err
	}
	input, err := os.Open(wshLocalPath)
	if err != nil {
		return fmt.Errorf("cannot open local file %s: %w", wshLocalPath, err)
	}
	defer input.Close()
	installWords := map[string]string{
		"installDir":  filepath.ToSlash(filepath.Dir(wavebase.RemoteFullWshBinPath)),
		"tempPath":    wavebase.RemoteFullWshBinPath + ".temp",
		"installPath": wavebase.RemoteFullWshBinPath,
	}
	var installCmd bytes.Buffer
	if err := installTemplate.Execute(&installCmd, installWords); err != nil {
		return fmt.Errorf("failed to prepare install command: %w", err)
	}
	blocklogger.Infof(ctx, "[conndebug] copying %q to remote server %q\n", wshLocalPath, wavebase.RemoteFullWshBinPath)
	genCmd, err := genconn.MakeSSHCmdClient(client, genconn.CommandSpec{
		Cmd: installCmd.String(),
	})
	if err != nil {
		return fmt.Errorf("failed to create remote command: %w", err)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check that the file printed in the error message exists (ls) and is readable; reinstall/repair Wave Terminal to restore the wsh binary.
  2. Verify the clientOs/clientArch passed to CpWshToRemote are correct — a wrong arch makes GetLocalWshBinaryPath point at a non-existent variant.
  3. Rebuild the wsh binary for the target platform if running from source, placing it where GetLocalWshBinaryPath expects.
  4. Check file permissions and AV quarantine logs if the path exists but cannot be opened.

Example fix

// before
_, err := connutil.CpWshToRemote(ctx, client, clientOs, "armv7") // variant not shipped locally
// after
if _, err := os.Stat(localPath); os.IsNotExist(err) {
    return fmt.Errorf("wsh binary missing for %s/%s; reinstall Wave", clientOs, clientArch)
}
err := connutil.CpWshToRemote(ctx, client, clientOs, clientArch)
Defensive patterns

Strategy: validation

Validate before calling

p, err := shellutil.GetLocalWshBinaryPath(wavebase.WaveVersion, clientOs, clientArch)
if err != nil { return err }
if fi, err := os.Stat(p); err != nil || fi.IsDir() {
    return fmt.Errorf("local wsh binary missing at %s for %s/%s", p, clientOs, clientArch)
}

Try / catch

err := connutil.CpWshToRemote(ctx, client, clientOs, clientArch)
if err != nil && strings.Contains(err.Error(), "cannot open local file") {
    return fmt.Errorf("wsh binary not installed locally; reinstall Wave Terminal: %w", err)
}

Prevention

When it happens

Trigger: Calling CpWshToRemote (via UpdateWsh or InstallWsh) when the local wsh binary file does not exist at the version/arch-derived path, the file permissions deny read, or the binary was deleted/moved after install.

Common situations: Running a dev build where the wsh binary was never placed at the expected path; mismatched clientOs/clientArch causing a lookup of a binary variant not shipped; antivirus quarantining the binary; partial upgrades removing old-version binaries.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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