{"record":{"id":"8ef4c6ae8987fe28","repo":"wavetermdev/waveterm","slug":"error-checking-job-manager-process-w","errorCode":null,"errorMessage":"error checking job manager process: %w","messagePattern":"error checking job manager process: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshrpc/wshremote/wshremote_job.go","lineNumber":346,"sourceCode":"\tconn := impl.getJobManagerConnection(data.JobId)\n\tif conn == nil {\n\t\tlog.Printf(\"RemoteDisconnectFromJobManagerCommand: no connection found for jobid=%s\\n\", data.JobId)\n\t\treturn nil\n\t}\n\n\tif conn.CleanupFn != nil {\n\t\tconn.CleanupFn()\n\t\tlog.Printf(\"RemoteDisconnectFromJobManagerCommand: cleanup completed for jobid=%s\\n\", data.JobId)\n\t}\n\n\treturn nil\n}\n\nfunc (impl *ServerImpl) RemoteTerminateJobManagerCommand(ctx context.Context, data wshrpc.CommandRemoteTerminateJobManagerData) error {\n\tlog.Printf(\"RemoteTerminateJobManagerCommand: terminating job manager, jobid=%s, pid=%d\\n\", data.JobId, data.JobManagerPid)\n\tproc, err := isProcessRunning(data.JobManagerPid, data.JobManagerStartTs)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error checking job manager process: %w\", err)\n\t}\n\tif proc == nil {\n\t\tlog.Printf(\"RemoteTerminateJobManagerCommand: job manager process not running, jobid=%s\\n\", data.JobId)\n\t\treturn nil\n\t}\n\terr = proc.SendSignal(syscall.SIGTERM)\n\tif err != nil {\n\t\tlog.Printf(\"failed to send SIGTERM to job manager: %v\", err)\n\t} else {\n\t\tlog.Printf(\"RemoteTerminateJobManagerCommand: sent SIGTERM to job manager process, jobid=%s, pid=%d\\n\", data.JobId, data.JobManagerPid)\n\t}\n\treturn nil\n}\n","sourceCodeStart":328,"sourceCodeEnd":360,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshrpc/wshremote/wshremote_job.go#L328-L360","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Check the wrapped cause for an OS/permission error (e.g. EPERM reading process info).","Retry as the same user that started the job manager, or run with sufficient privileges.","Treat as best-effort: proceed to kill by pid or clean up job state on the next reconnect if SIGTERM cannot be attempted.","Verify the remote platform supports the isProcessRunning implementation used by wsh."],"exampleFix":"// before\nproc, err := isProcessRunning(data.JobManagerPid, data.JobManagerStartTs)\nif err != nil {\n    return fmt.Errorf(\"error checking job manager process: %w\", err)\n}\n// after\nproc, err := isProcessRunning(data.JobManagerPid, data.JobManagerStartTs)\nif err != nil {\n    log.Printf(\"process check failed (%v), attempting best-effort signal\", err)\n    proc = nil // or fall through to a direct kill by pid\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isProcessCheckError(err error) bool {\n    return err != nil && !errors.Is(err, os.ErrNotExist)\n}","tryCatchPattern":"if err := wshclient.RemoteTerminateJobManagerCommand(ctx, data, nil); err != nil {\n    if isProcessCheckError(err) {\n        // fall back to best-effort cleanup: mark job manager state unknown\n        log.Printf(\"could not verify job manager pid %d: %v\", data.JobManagerPid, err)\n    }\n}","preventionTips":["Start the job manager as the same user that will terminate it","Handle EPERM/EACCES from process inspection gracefully","Treat process-state checks as best-effort in containers/restricted environments","Persist JobManagerStartTs correctly so stale-pid collisions are detected"],"tags":["process","remote-execution","job-manager"],"backgroundTag":"process-state-unknown","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}