hashicorp/nomad · error
failed to create terminal: %v
Error message
failed to create terminal: %v
What it means
newTerminalSocket creates a socket pair via lutils.NewSockPair to serve as the task's terminal (pty parent/tty child). If creating the socket pair fails (e.g. the unix socket temp path is unusable), the error is wrapped as "failed to create terminal". Without the terminal pair the container cannot be launched with an attached TTY.
Source
Thrown at drivers/shared/executor/executor_linux_cgo.go:579
}
}
var exitCode int
if status, ok := ps.Sys().(syscall.WaitStatus); ok {
exitCode = status.ExitStatus()
}
return buf.Bytes(), exitCode, nil
case <-time.After(time.Until(deadline)):
process.Signal(os.Kill)
return nil, 0, context.DeadlineExceeded
}
}
func (l *LibcontainerExecutor) newTerminalSocket() (pty func() (*os.File, error), tty *os.File, err error) {
parent, child, err := lutils.NewSockPair("socket")
if err != nil {
return nil, nil, fmt.Errorf("failed to create terminal: %v", err)
}
return func() (*os.File, error) { return lutils.RecvFile(parent) }, child, err
}
func (l *LibcontainerExecutor) ExecStreaming(ctx context.Context, cmd []string, tty bool,
stream drivers.ExecTaskStream) error {
// the task process will be started by the container
process := &libcontainer.Process{
Args: cmd,
Env: l.userProc.Env,
UID: l.userProc.UID,
Init: false,
Cwd: l.command.WorkDir,
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Check file descriptor usage (ulimit -n, lsof on nomad) and raise limits if EMFILE
- Ensure TMPDIR (default /tmp) is writable and has space for unix sockets
- Check LSM policies (SELinux/AppArmor) permitting unix socket creation by the Nomad process
- Upgrade/restart Nomad; some terminal socket cleanup bugs were fixed in later releases
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check temp dir writability and fd headroom
if f, err := os.CreateTemp(os.TempDir(), "sock-test"); err != nil {
return fmt.Errorf("TMPDIR unusable for sockets: %w", err)
} else { f.Close(); os.Remove(f.Name()) }
if n, _ := countOpenFDs(); n > fdLimit-64 { return fmt.Errorf("fd exhaustion risk") } Try / catch
if _, err := executor.Launch(cmd); err != nil && strings.Contains(err.Error(), "failed to create terminal") {
log.Printf("terminal socketpair failed: %v — check TMPDIR/fd limits", err)
} Prevention
- Keep /tmp (or TMPDIR) writable with space for unix sockets
- Raise RLIMIT_NOFILE for the Nomad process
- Ensure SELinux/AppArmor allows unix socket creation
- Keep Nomad updated for terminal socket cleanup fixes
When it happens
Trigger: lutils.NewSockPair("socket") returns an error: it cannot create/listen on the unix socket backing file, typically due to TMPDIR problems, too many open files, or permission issues in the temp directory.
Common situations: TMPDIR full or read-only so socketpair's temp socket path cannot be created; process hit the file-descriptor limit (ulimit -n) so socket creation fails EMFILE; SELinux/AppArmor blocking unix socket creation; /tmp cleaned by systemd-tmpfiles while sockets open (a known Nomad issue class).
Related errors
- ErrCgroupMustBeSet
- ExecStreaming: %w
- unable to get orphaned task PIDs: %v
- unable to send signal to process %d: %v
- orphaned processes %v have not been removed from cgroups pid
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/30cab6a1f5ef189d.
Report an issue: GitHub.