git-ecosystem/git-credential-manager · error · IOException
Failed to read initial terminal settings.
Error message
Failed to read initial terminal settings.
What it means
LinuxAnsiConsoleInput.RawModeContext captures the terminal's current termios settings via tcgetattr so they can be restored after raw mode; if the tcgetattr syscall fails (non-zero return) the constructor throws IOException. Without the original settings the code cannot safely enter or later restore raw mode.
Solutions
- Run the tool in a real terminal (allocate a TTY: docker run -t, script/expect in CI)
- Check Isatty/Console.IsInputRedirected before requesting raw mode and fall back to non-interactive input
- Verify the fd passed to RawModeContext is the terminal's stdin (0) and still open
- For non-interactive environments, supply credentials via config/environment instead of terminal prompts
Example fix
// before
using var raw = new RawModeContext(fd); // throws when stdin is piped
// after
if (Console.IsInputRedirected || !IsATty(fd))
throw new InvalidOperationException("Interactive terminal required; run in a TTY or use non-interactive auth.");
using var raw = new RawModeContext(fd); Defensive patterns
Strategy: try-catch
Validate before calling
if (Console.IsInputRedirected)
throw new InvalidOperationException("Raw terminal mode requires an interactive TTY; stdin is redirected."); Type guard
bool CanUseRawMode(int fd) => !Console.IsInputRedirected && LinuxAnsiConsoleInput.IsATty(fd);
Try / catch
try
{
using var raw = new RawModeContext(fd);
// interactive prompt
}
catch (IOException ex) when (ex.Message == "Failed to read initial terminal settings.")
{
logger.LogWarning("No TTY available; falling back to non-interactive authentication");
} Prevention
- Check IsInputRedirected / isatty before enabling raw mode and provide a non-interactive fallback
- Allocate a TTY in CI/containers (docker run -t, script -c) when interactive prompts are needed
- Offer environment/config-based credentials so prompts are never required in headless environments
When it happens
Trigger: Constructing RawModeContext(fd) when tcgetattr fails — fd is not a TTY (piped stdin, redirected output), fd is invalid/closed, or running in an environment without a controlling terminal.
Common situations: Running GCM's interactive prompts under CI, piping input (echo | gcm), running inside an IDE console or systemd service without a TTY, or docker run without -t.
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
- Failed to enter raw terminal mode.
- Failed to read initial terminal settings.
- Failed to enter raw terminal mode.
- Failed to open for reading.
- Failed to open for writing.
AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11).
Data as JSON: /api/errors/e8bbc589a4b88e14.
Report an issue: GitHub.
Appendix: source
Thrown at src/Core/Interop/Linux/LinuxAnsiConsoleInput.cs:33
protected override IDisposable EnterRawMode(PosixFileDescriptor fd)
{
return new RawModeContext(fd);
}
private sealed class RawModeContext : IDisposable
{
private readonly int _fd;
private termios_Linux _original;
private bool _isDisposed;
public RawModeContext(int fd)
{
_fd = fd;
if (Termios_Linux.tcgetattr(_fd, out termios_Linux t) != 0)
{
throw new System.IO.IOException("Failed to read initial terminal settings.");
}
_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);
View on GitHub (pinned to e8ce762cd0)