felixse/FluentTerminal · critical · Win32Exception
Could not get console screen buffer.
Error message
Could not get console screen buffer.
What it means
Thrown by Terminal.GetConsoleScreenBuffer when CreateFileW on the console output pseudo-filename (CONOUT$) returns INVALID_HANDLE_VALUE (-1). This handle is needed to query/set console mode for VT processing even when STDOUT is redirected (e.g. by Visual Studio). A -1 return means the console screen buffer could not be opened.
Source
Thrown at FluentTerminal.SystemTray/Services/ConPty/Terminal.cs:153
/// A helper method that opens a handle on the console's screen buffer, which will allow us to get its output,
/// even if STDOUT has been redirected (which Visual Studio does by default).
/// </summary>
/// <returns>A file handle to the console's screen buffer.</returns>
/// <remarks>This is described in more detail here: https://docs.microsoft.com/en-us/windows/console/console-handles </remarks>
private SafeFileHandle GetConsoleScreenBuffer()
{
IntPtr file = CreateFileW(
ConsoleOutPseudoFilename,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE,
IntPtr.Zero,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
IntPtr.Zero);
if (file == new IntPtr(-1))
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not get console screen buffer.");
}
return new SafeFileHandle(file, true);
}
#region IDisposable Support
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true);
}
private bool alreadyDisposed = false;
public void Dispose(bool disposeManaged)
{
if (alreadyDisposed)View on GitHub (pinned to ba83ec485e)
Solutions
- Ensure AllocConsole succeeded (error 13) before GetConsoleScreenBuffer is reached - the ctor orders these correctly, so an allocation failure is the usual upstream cause.
- Inspect Win32Exception.NativeErrorCode (ERROR_INVALID_HANDLE / access denied).
- Run the tray process in an interactive session with a genuine console.
- Fall back to WinPty if ConPty cannot obtain the screen buffer.
Example fix
// before
if (file == new IntPtr(-1))
throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not get console screen buffer.");
// after
int err = Marshal.GetLastWin32Error();
throw new Win32Exception(err, $"Could not get console screen buffer (Win32 error {err}). Ensure a console is allocated."); Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure a console exists before opening CONOUT$. if (GetConsoleWindow() == IntPtr.Zero) AllocConsole(); var h = CreateFileW(ConsoleOutPseudoFilename, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if (h == new IntPtr(-1)) throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
Try / catch
try { terminal = new Terminal(); }
catch (System.ComponentModel.Win32Exception ex) when (ex.Message.Contains("screen buffer")) { logger.Error(ex, $"CreateFileW(CONOUT$) failed (Win32 {ex.NativeErrorCode})"); fallbackToWinPty(); } Prevention
- Ensure AllocConsole succeeded before opening the screen buffer.
- Run in an interactive session with a real console.
- Inspect NativeErrorCode (ERROR_INVALID_HANDLE / access denied).
- Fall back to WinPty if ConPty cannot obtain the buffer.
When it happens
Trigger: Constructing a Terminal when there is no real console attached (so CONOUT$ does not resolve), or when GENERIC_WRITE|GENERIC_READ access is denied on the console. The check `file == new IntPtr(-1)` trips.
Common situations: AllocConsole failed or was skipped yet the code reaches here; running under a debugger/host that redirected all console handles; service/session without an interactive desktop console.
Related errors
- Could not allocate console for this process.
- Could not get console mode.
- Could not enable virtual terminal processing.
- failed to create pipe
- winpty_error_msg(errorHandle)
AI-assisted analysis of felixse/FluentTerminal@ba83ec485e (2026-08-13).
Data as JSON: /api/errors/8d5581bc1a633eb9.
Report an issue: GitHub.