git-ecosystem/git-credential-manager · error · IOException

Failed to enter raw terminal mode.

Error message

Failed to enter raw terminal mode.

What it means

RawModeContext's constructor calls tcsetattr to switch the terminal file descriptor into raw mode (echo, canonical processing, and signals disabled). When tcsetattr returns nonzero it throws this IOException, meaning the kernel rejected the termios change and the console input cannot be read in raw mode.

Solutions

  1. Ensure stdin/stdout are attached to a real TTY before constructing RawModeContext (check isatty on the fd)
  2. Run the process with a pseudo-terminal: `docker run -t`, `ssh -tt`, or `script -qec` in CI
  3. Fall back to line-based (cooked) console input when raw mode is unavailable
  4. Verify the fd passed to the RawModeContext constructor is valid and open

Example fix

// before
using var raw = new RawModeContext(fd); // throws if fd is not a TTY
// after
if (!IsAtty(fd)) { useCookedInput = true; }
else using var raw = new RawModeContext(fd);
Defensive patterns

Strategy: try-catch

Validate before calling

[DllImport("libc")] static extern int isatty(int fd);
if (isatty(fd) == 0) throw new InvalidOperationException("Raw mode requires a TTY");

Type guard

bool CanUseRawMode(int fd) => isatty(fd) != 0;

Try / catch

try { using var raw = new RawModeContext(fd); /* read keys */ }
catch (System.IO.IOException ex) when (ex.Message.Contains("raw terminal")) { FallBackToCookedInput(); }

Prevention

When it happens

Trigger: Creating a RawModeContext on a file descriptor that is not an interactive TTY (redirected stdin/stdout, pipes, background process without a controlling terminal), or when the fd is invalid/closed.

Common situations: Running the interactive console app with output piped or redirected (e.g. `app > log.txt`), under a non-TTY CI runner, inside Docker without -t, or via SSH with no pty allocated.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11). Data as JSON: /api/errors/0f756567fb8591b4. Report an issue: GitHub.

Appendix: source

Thrown at src/Core/Interop/Linux/LinuxAnsiConsoleInput.cs:54

            _original = t;

            // Raw mode: disable echo, line buffering, and signal interpretation.
            // With ISIG off the terminal does not generate SIGINT, so Ctrl+C
            // arrives as a 0x03 byte that the base adapter reads and acts on
            // directly. This is robust to GCM not being the terminal's
            // foreground process group.
            //
            // TCSANOW (apply immediately) rather than TCSAFLUSH: this context
            // is entered and disposed around each keystroke read, so the
            // terminal is only raw while we are actively reading. Flushing on
            // every transition would discard typeahead still queued in the tty
            // buffer (e.g. the trailing Enter of a pasted "<down><enter>"),
            // hanging the next read.
            t.c_lflag &= ~(LocalFlags.ECHO | LocalFlags.ICANON | LocalFlags.ISIG);

            if (Termios_Linux.tcsetattr(_fd, SetActionFlags.TCSANOW, ref t) != 0)
            {
                throw new System.IO.IOException("Failed to enter raw terminal mode.");
            }
        }

        public void Dispose()
        {
            if (_isDisposed) return;
            Termios_Linux.tcsetattr(_fd, SetActionFlags.TCSANOW, ref _original);
            _isDisposed = true;
        }
    }
}

View on GitHub (pinned to e8ce762cd0)