wavetermdev/waveterm · error
cannot create stdin pipe: %w
Error message
cannot create stdin pipe: %w
What it means
cmd.StdinPipe() failed while creating the stdin pipe used to deliver the job auth token to the wsh jobmanager child. StdinPipe creates an os.Pipe internally, so this is again an fd/resource allocation failure wrapped with %w.
Source
Thrown at pkg/wshrpc/wshremote/wshremote_job.go:159
return nil, err
}
log.Printf("RemoteStartJobCommand: wshPath=%s\n", wshPath)
readyPipeRead, readyPipeWrite, err := os.Pipe()
if err != nil {
return nil, fmt.Errorf("cannot create ready pipe: %w", err)
}
defer readyPipeRead.Close()
defer readyPipeWrite.Close()
cmd := exec.Command(wshPath, "jobmanager", "--jobid", data.JobId, "--clientid", data.ClientId)
if data.PublicKeyBase64 != "" {
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)View on GitHub (pinned to a4447c1563)
Solutions
- Fix fd leaks in the parent process and ensure pipes are closed after each job
- Raise RLIMIT_NOFILE (ulimit -n) for the server process
- Restart the server process if descriptors are exhausted
Defensive patterns
Strategy: try-catch
Validate before calling
var lim syscall.Rlimit
syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim)
if lim.Cur < 1024 {
return fmt.Errorf("fd limit too low (%d) to spawn job manager", lim.Cur)
} Try / catch
rtn, err := server.RemoteStartJobCommand(ctx, data)
if err != nil {
if strings.Contains(err.Error(), "cannot create stdin pipe") {
// fd exhaustion: leak-check and retry after raising limits
}
return err
} Prevention
- Track fds per job lifecycle; ensure StdinPipe is closed after token write (the code does this)
- Raise RLIMIT_NOFILE for the server
- Cap concurrent job starts
When it happens
Trigger: Calling RemoteStartJobCommand when pipe creation fails due to fd exhaustion or an OS-level pipe limit being reached.
Common situations: fd leaks accumulating across many spawned jobs; hitting the kernel pipe/fd limit on constrained hosts or containers.
Related errors
- cannot create stdout pipe: %w
- cannot create stderr pipe: %w
- cannot create ready pipe: %w
- failed to create stdout pipe: %w
- failed to start process: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/b4f349c663f4da89.
Report an issue: GitHub.