wavetermdev/waveterm · error

cannot create stdout pipe: %w

Error message

cannot create stdout pipe: %w

What it means

Returned when creating the stdout pipe for a spawned job fails, an OS resource-limit condition. The underlying error is wrapped with %w.

Source

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

	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)
	if _, err := stdin.Write([]byte(jobAuthTokenLine)); err != nil {
		cmd.Process.Kill()
		return nil, fmt.Errorf("cannot write job auth token: %w", err)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Fix fd leaks and ensure StdoutPipe handles are drained and closed per job
  2. Raise the file descriptor limit for the server process
  3. Cap concurrent job starts so pipe usage stays under the limit
Defensive patterns

Strategy: try-catch

Validate before calling

var lim syscall.Rlimit
syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim)
if lim.Cur-lim-used < 10 { /* approximate headroom check */ }

Try / catch

rtn, err := server.RemoteStartJobCommand(ctx, data)
if err != nil {
    if strings.Contains(err.Error(), "cannot create stdout pipe") {
        // pipe/fd allocation failed; inspect fd usage before retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling RemoteStartJobCommand when the parent process cannot allocate another pipe/file descriptor.

Common situations: Servers spawning many concurrent jobs without closing prior pipes; low fd ulimits in production containers.

Related errors


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