jesseduffield/lazygit · error
CreatePseudoConsole: %w
Error message
CreatePseudoConsole: %w
What it means
StartPty calls CreatePseudoConsole (the ConPTY API, Windows 10 1809+) to set up the pseudoconsole using the two pipe ends. On failure it closes the child-side pipe handles and returns this wrapped error. Typical causes: unsupported/old Windows build, conhost.exe problems, or exhausted console sessions.
Source
Thrown at pkg/commands/oscommands/pty_windows.go:320
// direct child of this process. The teardown in Close needs a handle to
// that conhost (see there), but Windows offers no way to obtain one
// from the HPCON, so identify it by diffing our conhost children around
// the call. Open a real handle right away so that pid reuse can't later
// misdirect the teardown's reap. If identification fails, the handle
// stays 0 and the teardown skips the reap.
var hpc, conhost windows.Handle
size := clampPtySize(cols, rows)
conhostScanMu.Lock()
conhostsBefore := conhostChildren()
err = windows.CreatePseudoConsole(size, inRead, outWrite, 0, &hpc)
if err == nil {
conhost = openNewConhostChild(conhostsBefore)
}
conhostScanMu.Unlock()
if err != nil {
_ = windows.CloseHandle(inRead)
_ = windows.CloseHandle(outWrite)
return StartedPty{}, fmt.Errorf("CreatePseudoConsole: %w", err)
}
_ = windows.CloseHandle(inRead)
_ = windows.CloseHandle(outWrite)
defer func() {
if err != nil {
windows.ClosePseudoConsole(hpc)
if conhost != 0 {
_ = windows.CloseHandle(conhost)
}
}
}()
// The child goes into a job object so that the teardown in Close can
// terminate the whole process tree. KILL_ON_JOB_CLOSE makes the OS do
// that when the last handle to the job is closed, which doubles as a
// safety net: if lazygit exits without running the teardown, the handle
// is closed for it and the tree is reaped.
job, err := windows.CreateJobObject(nil, nil)View on GitHub (pinned to c477a2959b)
Solutions
- Verify Windows 10 1809+ / Server 2019+ (`winver`); on older builds PTY-backed features can't work.
- Ensure conhost.exe exists and isn't blocked by policy/AV; try 'conhost.exe' from a terminal.
- Sign out/in (or reboot) to reset console session state if it worked before.
- Update lazygit — the integration layer here keeps changing with Windows releases.
Defensive patterns
Strategy: fallback
Validate before calling
// Feature-detect ConPTY before attempting StartPty:
func conptyAvailable() bool {
v := windows.RtlGetVersion() // or syscall GetVersionEx equivalent
return v.Major > 10 || (v.Major == 10 && v.Build >= 17763) // 1809
} Try / catch
sp, err := oscommands.StartPty(cmd, cols, rows)
if err != nil {
if strings.Contains(err.Error(), "CreatePseudoConsole") {
// pre-1809 Windows or conhost unavailable: run without a pty
return runWithoutPty(cmd)
}
return err
} Prevention
- Require Windows 10 1809+ for PTY features; gate on OS build at startup.
- Ensure conhost.exe is present and not blocked by policy/AV on managed machines.
- Provide a non-PTY execution fallback so older Windows still works.
When it happens
Trigger: CreatePseudoConsole returning an error: running on Windows older than 10 1809 (API missing), conhost.exe missing/blocked, too many active ConPTY sessions, or corrupted console driver state.
Common situations: Old Windows Server or LTSB/LTSC builds predating ConPTY; locked-down machines where conhost is disallowed; terminal-driver issues after RDP/session switches.
Related errors
AI-assisted analysis of jesseduffield/lazygit@c477a2959b (2026-08-15).
Data as JSON: /api/errors/1ddcad8b7df60c5f.
Report an issue: GitHub.