wavetermdev/waveterm · error
cannot start job manager: %w
Error message
cannot start job manager: %w
What it means
cmd.Start() failed to launch the 'wsh jobmanager --jobid ... --clientid ...' child process. The error from os/exec (typically exec.ErrNotFound wrapped as 'exec: "wsh": executable file not found in $PATH', or a permission error) is wrapped with %w.
Source
Thrown at pkg/wshrpc/wshremote/wshremote_job.go:172
cmd.Env = append(os.Environ(), "WAVETERM_PUBLICKEY="+data.PublicKeyBase64)
}
cmd.ExtraFiles = []*os.File{readyPipeWrite}
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, fmt.Errorf("cannot create stdin pipe: %w", err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("cannot create stdout pipe: %w", err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
return nil, fmt.Errorf("cannot create stderr pipe: %w", err)
}
log.Printf("RemoteStartJobCommand: created pipes\n")
if err := cmd.Start(); err != nil {
return nil, fmt.Errorf("cannot start job manager: %w", err)
}
readyPipeWrite.Close()
log.Printf("RemoteStartJobCommand: job manager process started\n")
jobAuthTokenLine := fmt.Sprintf("Wave-JobAccessToken:%s\n", data.JobAuthToken)
if _, err := stdin.Write([]byte(jobAuthTokenLine)); err != nil {
cmd.Process.Kill()
return nil, fmt.Errorf("cannot write job auth token: %w", err)
}
stdin.Close()
log.Printf("RemoteStartJobCommand: wrote auth token to stdin\n")
go func() {
scanner := bufio.NewScanner(stderr)
for scanner.Scan() {
line := scanner.Text()
log.Printf("RemoteStartJobCommand: stderr: %s\n", line)
}View on GitHub (pinned to a4447c1563)
Solutions
- Run 'wsh init' / reinstall the wsh binary on the remote host so getWshPath() resolves a valid executable
- Check permissions: chmod +x on the wsh binary and verify the path it resolves to
- Verify the install filesystem is mounted and not noexec
- Reproduce by running the resolved wshPath manually with the jobmanager args
Example fix
// before $ ls $(which wsh) which: no wsh in (...) // after $ wsh init # install the wsh binary on the remote host $ chmod +x ~/.local/bin/wsh
Defensive patterns
Strategy: validation
Validate before calling
wshPath, err := getWshPath() // or replicate: exec.LookPath("wsh")
if err != nil {
return fmt.Errorf("wsh binary not available: %w", err)
}
if info, err := os.Stat(wshPath); err != nil || info.Mode()&0o111 == 0 {
return fmt.Errorf("wsh binary missing or not executable: %s", wshPath)
} Type guard
func wshExecutableAvailable(path string) bool {
info, err := os.Stat(path)
return err == nil && !info.IsDir() && info.Mode()&0o111 != 0
} Try / catch
rtn, err := server.RemoteStartJobCommand(ctx, data)
if err != nil {
if strings.Contains(err.Error(), "cannot start job manager") {
// reinstall wsh on the remote ('wsh init') and retry once
}
return err
} Prevention
- Run 'wsh init' on every remote host before using jobs
- Verify the binary is executable and on the expected path
- Reinstall wsh after Wave upgrades to keep versions in sync
When it happens
Trigger: The resolved wshPath from getWshPath() points to a missing, deleted, or non-executable binary; the binary exists but lacks +x; or the filesystem housing it is unavailable.
Common situations: Wave not fully installed / wsh binary not installed on the remote host; PATH differences between server env and expected install location; binary removed by cleanup or an upgrade; noexec mount on the install directory.
Related errors
- failed to start process: %w
- failed to start command: %w
- procinfo: process not found
- accessing file %s: %w
- reading directory %s: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/4571a98c9a317485.
Report an issue: GitHub.