gravitational/teleport · error

failed to set stdin mode: %w

Error message

failed to set stdin mode: %w

What it means

When input capture is requested, initTerminal reconfigures the stdin console mode (raw input, VT input, no echo/line processing). If SetConsoleMode(stdin) fails, the code first attempts to restore the original stdout mode (logging if that restore also fails) and then returns this wrapped error. The terminal session setup is aborted; stdout mode restoration is best-effort.

Source

Thrown at lib/client/terminal/terminal_windows.go:88

		newInMode &^= winterm.ENABLE_PROCESSED_INPUT

		newInMode |= winterm.ENABLE_EXTENDED_FLAGS
		newInMode |= winterm.ENABLE_INSERT_MODE
		newInMode |= winterm.ENABLE_QUICK_EDIT_MODE
		newInMode |= winterm.ENABLE_VIRTUAL_TERMINAL_INPUT

		err = winterm.SetConsoleMode(uintptr(stdinFd), newInMode)
		if err != nil {
			// Attempt to reset the stdout mode before returning.
			err = winterm.SetConsoleMode(uintptr(stdoutFd), oldOutMode)
			if err != nil {
				log.ErrorContext(context.Background(), "Failed to reset terminal output mode",
					"original_output_mode", oldOutMode,
					"error", err,
				)
			}

			return func() {}, fmt.Errorf("failed to set stdin mode: %w", err)
		}
	}

	return func() {
		err := winterm.SetConsoleMode(uintptr(stdoutFd), oldOutMode)
		if err != nil {
			log.ErrorContext(context.Background(), "Failed to reset terminal output mode",
				"original_output_mode", oldOutMode,
				"error", err,
			)
		}

		if input {
			err = winterm.SetConsoleMode(uintptr(stdinFd), oldInMode)
			if err != nil {
				log.ErrorContext(context.Background(), "Failed to reset terminal input mode",
					"original_input_mode", oldInMode,
					"error", err,

View on GitHub (pinned to 1283425b60)

Solutions

  1. Ensure stdin is an interactive console before requesting input=true; check term.IsTerminal(os.Stdin.Fd()) first.
  2. Call InitRaw(false) when stdin is redirected — output-only raw mode avoids touching the stdin console mode entirely.
  3. Avoid piping input when an interactive session is expected; use the tool's non-interactive batch mode instead.
  4. Update to a Windows 10 1607+ / Windows Terminal host if the failure is due to unsupported VT input flags.

Example fix

// before
err := t.InitRaw(true)

// after
if term.IsTerminal(os.Stdin.Fd()) {
    err = t.InitRaw(true)
} else {
    err = t.InitRaw(false)
}
if err != nil {
    return trace.Wrap(err)
}
Defensive patterns

Strategy: validation

Validate before calling

import "github.com/moby/term"

if !term.IsTerminal(os.Stdin.Fd()) {
    // request output-only raw mode; skips the stdin SetConsoleMode path entirely
    return t.InitRaw(false)
}

Type guard

func canCaptureRawInput() bool {
    return term.IsTerminal(os.Stdin.Fd())
}

Try / catch

cleanup, err := t.InitRaw(input)
if err != nil && strings.Contains(err.Error(), "failed to set stdin mode") {
    log.Warn("raw stdin capture failed; retrying output-only")
    cleanup, err = t.InitRaw(false)
    if err != nil {
        return trace.Wrap(err)
    }
}

Prevention

When it happens

Trigger: Calling Terminal.InitRaw(true) on Windows when SetConsoleMode(stdinFd, newInMode) fails: stdin is not a writable-mode console handle, the handle was closed or redirected between GetConsoleMode and SetConsoleMode, or the console host rejects ENABLE_VIRTUAL_TERMINAL_INPUT / ENABLE_EXTENDED_FLAGS combinations.

Common situations: Piping or redirecting stdin (e.g. `echo cmd | tsh ...`) while requesting interactive raw input; running under CI/agent harnesses with fake stdin; legacy console hosts that do not support ENABLE_VIRTUAL_TERMINAL_INPUT; a race where another process (e.g. a concurrent session) altered the stdin mode.

Related errors


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/12e191c2d6949e0b. Report an issue: GitHub.