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
- Check that the file printed in the error message exists (ls) and is readable; reinstall/repair Wave Terminal to restore the wsh binary.
- Verify the clientOs/clientArch passed to CpWshToRemote are correct — a wrong arch makes GetLocalWshBinaryPath point at a non-existent variant.
- Rebuild the wsh binary for the target platform if running from source, placing it where GetLocalWshBinaryPath expects.
- 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
- Verify the wsh binary exists for the current version/arch before offering install/update actions.
- Keep clientOs/clientArch values consistent with the binaries actually shipped.
- Exclude the wsh binary path from antivirus/cleanup tooling.
- Rebuild/restore binaries after upgrading Wave from source.
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
- failed to prepare install command: %w
- error opening domain socket listener: %w
- nil wshrpc passed to wshclient
- accessing file %s: %w
- getting absolute path for %s: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/06bf0eff4ac95219.
Report an issue: GitHub.