slimtoolkit/slim · error

cannot create pipe for app %s stream: %w

Error message

cannot create pipe for app %s stream: %w

What it means

After opening the app's stream log file, dupAppStdStream creates an os.Pipe used to tee the app's output to both the live writer and the file. This error is returned when os.Pipe() fails, wrapping the OS error; the already-opened file is closed first.

Source

Thrown at pkg/app/sensor/monitor/composite.go:362

}

// Using simple io.MultiWriter(os.Stdout, os.File) would make cmd.Wait()
// block until either the cmd's stdout is closed or the multi-writer is closed.
// However, both are impossible. We need the Wait() to return much earlier
// than the process termination (see pkg/monitors/ptrace logic), and multi-writer
// cannot be closed at all. Hence, the pipe trick.
func dupAppStdStream(artifactsDir string, w io.Writer, kind string) (*os.File, *os.File, error) {
	filename := filepath.Join(artifactsDir, "app_"+kind+".log")

	f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0o644)
	if err != nil {
		return nil, nil, fmt.Errorf("cannot open file %q to duplicate app's %s stream: %w", filename, kind, err)
	}

	pr, pw, err := os.Pipe()
	if err != nil {
		f.Close()
		return nil, nil, fmt.Errorf("cannot create pipe for app %s stream: %w", kind, err)
	}

	go func() {
		n, err := io.Copy(io.MultiWriter(w, f), pr)
		log.Debugf("dupAppStdStream: io.Copy() finished; written=%d error=%v", n, err)
	}()

	return pw, f, nil
}

func closeAll(cs []io.Closer) {
	for _, c := range cs {
		errutil.WarnOn(c.Close())
	}
}

View on GitHub (pinned to 81940d17fa)

Solutions

  1. Check fd usage (lsof / ls /proc/<pid>/fd) and raise RLIMIT_NOFILE (ulimit -n) for the sensor process.
  2. Fix fd leaks in the surrounding application before starting the monitor.
  3. Retry after system load decreases if ENFILE (system-wide table full) is reported.

Example fix

// before (shell)
./sensor
// after (shell)
ulimit -n 65536 && ./sensor
Defensive patterns

Strategy: retry

Try / catch

mon, err := NewCompositeMonitor(cfg)
if err != nil && strings.Contains(err.Error(), "cannot create pipe") {
    // likely fd exhaustion; free descriptors and retry once
    runtime.GC()
    mon, err = NewCompositeMonitor(cfg)
}

Prevention

When it happens

Trigger: os.Pipe() failing during NewCompositeMonitor — practically only when the process has exhausted its file descriptor limit (EMFILE) or the kernel cannot allocate a pipe (ENFILE).

Common situations: Long-running hosts or leaked fds causing the process to hit RLIMIT_NOFILE; system-wide file table exhaustion under heavy load.

Related errors


AI-assisted analysis of slimtoolkit/slim@81940d17fa (2026-08-31). Data as JSON: /api/errors/aa46159ea42be7f7. Report an issue: GitHub.