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

  1. Fix fd leaks in the parent process and ensure pipes are closed after each job
  2. Raise RLIMIT_NOFILE (ulimit -n) for the server process
  3. 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

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


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