{"record":{"id":"09932c096e56ce35","repo":"hashicorp/nomad","slug":"failed-to-resize-tty-v","errorCode":null,"errorMessage":"failed to resize tty: %v","messagePattern":"failed to resize tty: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"drivers/shared/executor/exec_utils.go","lineNumber":199,"sourceCode":"\t\t\terrCh <- err\n\t\t\treturn\n\t\t}\n\n\t\tif m.Stdin != nil {\n\t\t\tif len(m.Stdin.Data) != 0 {\n\t\t\t\t_, err := stdin.Write(m.Stdin.Data)\n\t\t\t\tif err != nil {\n\t\t\t\t\terrCh <- err\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tif m.Stdin.Close {\n\t\t\t\tstdin.Close()\n\t\t\t}\n\t\t} else if m.TtySize != nil {\n\t\t\terr := setTTYSize(stdin, m.TtySize.Height, m.TtySize.Width)\n\t\t\tif err != nil {\n\t\t\t\terrCh <- fmt.Errorf(\"failed to resize tty: %v\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc handleStdout(logger hclog.Logger, reader io.Reader, wg *sync.WaitGroup, send func(*drivers.ExecTaskStreamingResponseMsg) error, errCh chan<- error) {\n\tdefer wg.Done()\n\n\tbuf := make([]byte, 4096)\n\tfor {\n\t\tn, err := reader.Read(buf)\n\t\t// always send output first if we read something\n\t\tif n > 0 {\n\t\t\tif err := send(&drivers.ExecTaskStreamingResponseMsg{\n\t\t\t\tStdout: &dproto.ExecTaskStreamingIOOperation{\n\t\t\t\t\tData: buf[:n],\n\t\t\t\t},","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/shared/executor/exec_utils.go#L181-L217","documentation":"handleStdin processes stdin frames from the client; when a frame carries a TtySize it resizes the pty via setTTYSize. On failure it pushes this wrapped error onto errCh, which runTTY/runNoTTY surface to the caller. The process keeps running but the terminal resize did not apply.","triggerScenarios":"Client sends a stdin message with TtySize set (terminal window resize in exec/alloc UI or `nomad alloc exec` with tty) and setTTYSize fails — most often because stdin is not actually a pty (TIOCSWINSZ ioctl fails ENOTTY) or the pty was already closed.","commonSituations":"Attaching to a non-TTY task that receives resize frames, pty closed after process exit while a resize frame is in flight, running inside environments without pty support (CI, restricted containers), Windows terminal clients negotiating sizes on non-pty sessions.","solutions":["Verify the task was started with tty=true if interactive resize is expected","Ignore/retry: the resize error is often transient after process exit; restart the exec session","Check /dev/pts availability in the execution environment","Update the client so resize frames are only sent for TTY sessions"],"exampleFix":"// before\n// nomad alloc exec -task web /bin/sh  # task started without tty\n// after\n// ensure driver task config has tty = true, or omit TtySize frames for non-tty tasks","handlingStrategy":"retry","validationCode":"func canResize(taskTTY bool) error {\n  if !taskTTY { return errors.New(\"resize frame requested for non-tty task\") }\n  if _, err := os.Stat(\"/dev/pts\"); err != nil { return err }\n  return nil\n}","typeGuard":null,"tryCatchPattern":"if err := attachExecSession(); err != nil {\n  if strings.Contains(err.Error(), \"failed to resize tty\") {\n    // transient: pty may have closed; retry once, then drop resize handling\n    time.Sleep(100 * time.Millisecond)\n    return retryAttach()\n  }\n  return err\n}","preventionTips":["Only send TtySize frames for sessions started with tty=true","Handle resize errors as non-fatal in terminal clients","Ensure devpts is mounted in exec environments","Close sessions promptly after process exit"],"tags":["tty","resize","stdin","nomad-executor"],"backgroundTag":"tty-resize-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}