{"record":{"id":"30cab6a1f5ef189d","repo":"hashicorp/nomad","slug":"failed-to-create-terminal-v","errorCode":null,"errorMessage":"failed to create terminal: %v","messagePattern":"failed to create terminal: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/shared/executor/executor_linux_cgo.go","lineNumber":579,"sourceCode":"\t\t\t}\n\t\t}\n\t\tvar exitCode int\n\t\tif status, ok := ps.Sys().(syscall.WaitStatus); ok {\n\t\t\texitCode = status.ExitStatus()\n\t\t}\n\t\treturn buf.Bytes(), exitCode, nil\n\n\tcase <-time.After(time.Until(deadline)):\n\t\tprocess.Signal(os.Kill)\n\t\treturn nil, 0, context.DeadlineExceeded\n\t}\n\n}\n\nfunc (l *LibcontainerExecutor) newTerminalSocket() (pty func() (*os.File, error), tty *os.File, err error) {\n\tparent, child, err := lutils.NewSockPair(\"socket\")\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to create terminal: %v\", err)\n\t}\n\n\treturn func() (*os.File, error) { return lutils.RecvFile(parent) }, child, err\n\n}\n\nfunc (l *LibcontainerExecutor) ExecStreaming(ctx context.Context, cmd []string, tty bool,\n\tstream drivers.ExecTaskStream) error {\n\n\t// the task process will be started by the container\n\tprocess := &libcontainer.Process{\n\t\tArgs: cmd,\n\t\tEnv:  l.userProc.Env,\n\t\tUID:  l.userProc.UID,\n\t\tInit: false,\n\t\tCwd:  l.command.WorkDir,\n\t}\n","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/shared/executor/executor_linux_cgo.go#L561-L597","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check temp dir writability and fd headroom\nif f, err := os.CreateTemp(os.TempDir(), \"sock-test\"); err != nil {\n    return fmt.Errorf(\"TMPDIR unusable for sockets: %w\", err)\n} else { f.Close(); os.Remove(f.Name()) }\nif n, _ := countOpenFDs(); n > fdLimit-64 { return fmt.Errorf(\"fd exhaustion risk\") }","typeGuard":null,"tryCatchPattern":"if _, err := executor.Launch(cmd); err != nil && strings.Contains(err.Error(), \"failed to create terminal\") {\n    log.Printf(\"terminal socketpair failed: %v — check TMPDIR/fd limits\", err)\n}","preventionTips":["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"],"tags":["pty","terminal","socket","linux","executor"],"backgroundTag":"terminal-socket-create-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}