wavetermdev/waveterm · error

error checking job manager process: %w

Error message

error checking job manager process: %w

What it means

RemoteTerminateJobManagerCommand checks whether the remote job manager process is still running (via isProcessRunning comparing pid and start timestamp) before sending SIGTERM. This error wraps a failure of that check itself — i.e. the code could not determine the process state (OS-level lookup error), so termination is aborted. It does not mean the process is running or not; the state is unknown.

Source

Thrown at pkg/wshrpc/wshremote/wshremote_job.go:346

	conn := impl.getJobManagerConnection(data.JobId)
	if conn == nil {
		log.Printf("RemoteDisconnectFromJobManagerCommand: no connection found for jobid=%s\n", data.JobId)
		return nil
	}

	if conn.CleanupFn != nil {
		conn.CleanupFn()
		log.Printf("RemoteDisconnectFromJobManagerCommand: cleanup completed for jobid=%s\n", data.JobId)
	}

	return nil
}

func (impl *ServerImpl) RemoteTerminateJobManagerCommand(ctx context.Context, data wshrpc.CommandRemoteTerminateJobManagerData) error {
	log.Printf("RemoteTerminateJobManagerCommand: terminating job manager, jobid=%s, pid=%d\n", data.JobId, data.JobManagerPid)
	proc, err := isProcessRunning(data.JobManagerPid, data.JobManagerStartTs)
	if err != nil {
		return fmt.Errorf("error checking job manager process: %w", err)
	}
	if proc == nil {
		log.Printf("RemoteTerminateJobManagerCommand: job manager process not running, jobid=%s\n", data.JobId)
		return nil
	}
	err = proc.SendSignal(syscall.SIGTERM)
	if err != nil {
		log.Printf("failed to send SIGTERM to job manager: %v", err)
	} else {
		log.Printf("RemoteTerminateJobManagerCommand: sent SIGTERM to job manager process, jobid=%s, pid=%d\n", data.JobId, data.JobManagerPid)
	}
	return nil
}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check the wrapped cause for an OS/permission error (e.g. EPERM reading process info).
  2. Retry as the same user that started the job manager, or run with sufficient privileges.
  3. Treat as best-effort: proceed to kill by pid or clean up job state on the next reconnect if SIGTERM cannot be attempted.
  4. Verify the remote platform supports the isProcessRunning implementation used by wsh.

Example fix

// before
proc, err := isProcessRunning(data.JobManagerPid, data.JobManagerStartTs)
if err != nil {
    return fmt.Errorf("error checking job manager process: %w", err)
}
// after
proc, err := isProcessRunning(data.JobManagerPid, data.JobManagerStartTs)
if err != nil {
    log.Printf("process check failed (%v), attempting best-effort signal", err)
    proc = nil // or fall through to a direct kill by pid
}
Defensive patterns

Strategy: try-catch

Type guard

func isProcessCheckError(err error) bool {
    return err != nil && !errors.Is(err, os.ErrNotExist)
}

Try / catch

if err := wshclient.RemoteTerminateJobManagerCommand(ctx, data, nil); err != nil {
    if isProcessCheckError(err) {
        // fall back to best-effort cleanup: mark job manager state unknown
        log.Printf("could not verify job manager pid %d: %v", data.JobManagerPid, err)
    }
}

Prevention

When it happens

Trigger: isProcessRunning fails: OS error reading /proc (Linux) or equivalent for the given pid, permission denied inspecting another user's process, or the process-table lookup API returning an unexpected error.

Common situations: Job manager ran as a different user so its process info is unreadable; container/restricted environment where /proc is limited; stale pid that collides with a protected system process; platform differences (macOS vs Linux ps semantics).

Related errors


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