dagger/dagger · critical
failed to start session subprocess: %w
Error message
failed to start session subprocess: %w
What it means
startSessionSubprocess (cmd/init, running inside the engine init process) forks a detached session subprocess (Setsid) with a pipe for readiness signaling. This error wraps any failure from cmd.Start() — the OS refused to spawn the child process. The wrapped error carries the underlying syscall reason.
Source
Thrown at cmd/init/main.go:227
r, w, err := os.Pipe()
if err != nil {
return err
}
// start the session subprocess
cmd := exec.Command("/proc/self/exe")
// forwarding our stdio ensures that a panic in the child process won't get hidden and any other logging works too
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.ExtraFiles = []*os.File{w}
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
err = cmd.Start()
if err != nil {
return fmt.Errorf("failed to start session subprocess: %w", err)
}
// wait for the session attachables to be ready (or the child to die)
// need to close our dup of the write end of the pipe
if err := w.Close(); err != nil {
return fmt.Errorf("failed to close pipe: %w", err)
}
doneCh := make(chan struct{})
go func() {
defer close(doneCh)
io.Copy(io.Discard, r)
}()
// something really really wrong would have to happen for this to block indefinitely, but be
// cautious anyways w/ an overly generous timeout
select {
case <-doneCh:View on GitHub (pinned to 82ba2681db)
Solutions
- Read the wrapped %w error to identify the syscall cause (ENOENT/EACCES/EAGAIN)
- Verify the session subprocess binary exists and is executable at the configured path
- Check container security profiles (seccomp, AppArmor) and ulimits permit spawning the process
- Free memory / raise process limits (nproc) if EAGAIN or OOM is reported
- Restart the engine/pod if a transient resource exhaustion caused the fork failure
Example fix
// before: image stripped of the session binary -> ENOENT // after: ensure the binary ships and is executable // Dockerfile: COPY --from=build /out/dagger-session /usr/local/bin/dagger-session // RUN chmod +x /usr/local/bin/dagger-session
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: ensure the session binary is present and executable
if fi, err := os.Stat(sessionBinPath); err != nil || fi.IsDir() || fi.Mode()&0o111 == 0 {
return fmt.Errorf("session binary %s missing or not executable", sessionBinPath)
} Try / catch
if err := startSessionSubprocess(...); err != nil {
var execErr *exec.Error
if errors.As(err, &execErr) {
log.Printf("session binary %q unusable: %v", execErr.Name, execErr.Err)
} else if errors.Is(err, os.ErrPermission) {
log.Printf("permission denied spawning session subprocess")
}
return err
} Prevention
- Ship the session subprocess binary in the image and chmod +x it
- Keep container seccomp/AppArmor profiles permissive enough for fork/exec
- Raise nproc ulimits for workloads spawning many processes
- Monitor memory to avoid fork failures under pressure (EAGAIN/OOM)
When it happens
Trigger: mainInit -> startSessionSubprocess calls cmd.Start() and the exec fails: binary not found (ENOENT), not executable (EACCES), fork/resource limits hit (EAGAIN), or out of memory.
Common situations: Session binary missing or corrupted in the container image; wrong executable path; seccomp/AppArmor or PID namespace restrictions blocking exec; hitting process limits (ulimit -u) under heavy load.
Related errors
- failed to close pipe: %w
- timed out waiting for session subprocess to start
- failed to init temp repo: %w
- failed to init repo at %s: %w
- persisted module source sdk does not implement module init
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/fff7d681c53a1c18.
Report an issue: GitHub.