{"record":{"id":"4d6ab22a3025aabf","repo":"wavetermdev/waveterm","slug":"cannot-create-ready-pipe-w","errorCode":null,"errorMessage":"cannot create ready pipe: %w","messagePattern":"cannot create ready pipe: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshrpc/wshremote/wshremote_job.go","lineNumber":147,"sourceCode":"\tdefer impl.Lock.Unlock()\n\treturn impl.JobManagerMap[jobId]\n}\n\nfunc (impl *ServerImpl) RemoteStartJobCommand(ctx context.Context, data wshrpc.CommandRemoteStartJobData) (*wshrpc.CommandStartJobRtnData, error) {\n\tlog.Printf(\"RemoteStartJobCommand: starting, jobid=%s, clientid=%s\\n\", data.JobId, data.ClientId)\n\tif impl.Router == nil {\n\t\treturn nil, fmt.Errorf(\"cannot start remote job: no router available\")\n\t}\n\n\twshPath, err := impl.getWshPath()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlog.Printf(\"RemoteStartJobCommand: wshPath=%s\\n\", wshPath)\n\n\treadyPipeRead, readyPipeWrite, err := os.Pipe()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot create ready pipe: %w\", err)\n\t}\n\tdefer readyPipeRead.Close()\n\tdefer readyPipeWrite.Close()\n\n\tcmd := exec.Command(wshPath, \"jobmanager\", \"--jobid\", data.JobId, \"--clientid\", data.ClientId)\n\tif data.PublicKeyBase64 != \"\" {\n\t\tcmd.Env = append(os.Environ(), \"WAVETERM_PUBLICKEY=\"+data.PublicKeyBase64)\n\t}\n\tcmd.ExtraFiles = []*os.File{readyPipeWrite}\n\tstdin, err := cmd.StdinPipe()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot create stdin pipe: %w\", err)\n\t}\n\tstdout, err := cmd.StdoutPipe()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot create stdout pipe: %w\", err)\n\t}\n\tstderr, err := cmd.StderrPipe()","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshrpc/wshremote/wshremote_job.go#L129-L165","documentation":"os.Pipe() failed while creating the readiness-notification pipe pair used by the job manager child process to signal 'Wave-JobManagerStart'. This is a kernel-level fd allocation failure (EMFILE/ENFILE typically), surfaced wrapped with %w.","triggerScenarios":"Calling RemoteStartJobCommand when the process has exhausted its file descriptor limit or the OS cannot allocate pipes (fd table full, low memory).","commonSituations":"Long-running servers leaking file descriptors until hitting ulimit -n; systems with very low RLIMIT_NOFILE; containerized environments with small fd caps.","solutions":["Check fd usage (lsof / /proc/<pid>/fd) and fix descriptor leaks","Raise the soft/hard file descriptor limit (ulimit -n) or the container's nofile limit","Restart the process to clear leaked descriptors"],"exampleFix":"// before\n$ ulimit -n\n1024\n// after\n$ ulimit -n 65536  # or set LimitNOFILE=65536 in the systemd unit / nofile in container runtime","handlingStrategy":"try-catch","validationCode":"var lim syscall.Rlimit\nsyscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim)\nif lim.Cur < 1024 {\n    lim.Cur = 65536\n    syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim)\n}","typeGuard":null,"tryCatchPattern":"rtn, err := server.RemoteStartJobCommand(ctx, data)\nif err != nil {\n    var pe *os.PathError\n    if errors.As(err, &pe) {\n        // pipe allocation failure: check fd limits before retrying\n    }\n    return err\n}","preventionTips":["Monitor open fd counts on the server process","Close all pipes/streams after each job completes","Set generous RLIMIT_NOFILE in the service unit or container"],"tags":["os","file-descriptors","pipes","resource-limits"],"backgroundTag":"too-many-open-files","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}