jesseduffield/lazygit · error
CreatePipe (out): %w
Error message
CreatePipe (out): %w
What it means
Second pipe-creation step in StartPty: the pipe that carries the child's stdout/stderr out of the pseudoconsole. If this CreatePipe fails, the already-created stdin pipe (inRead/inWrite) is closed and this wrapped error returns. Same root causes as any CreatePipe failure: kernel handle/memory resources unavailable.
Source
Thrown at pkg/commands/oscommands/pty_windows.go:290
return h
}
func StartPty(cmd *exec.Cmd, cols, rows uint16) (sp StartedPty, err error) {
// Two pipes: one for the child's stdin (we never write to it, but ConPTY
// needs a handle), one for the child's stdout/stderr multiplexed through
// the pseudoconsole.
var inRead, inWrite, outRead, outWrite windows.Handle
if err = windows.CreatePipe(&inRead, &inWrite, nil, 0); err != nil {
return StartedPty{}, fmt.Errorf("CreatePipe (in): %w", err)
}
defer func() {
if err != nil {
_ = windows.CloseHandle(inWrite)
}
}()
if err = windows.CreatePipe(&outRead, &outWrite, nil, 0); err != nil {
_ = windows.CloseHandle(inRead)
return StartedPty{}, fmt.Errorf("CreatePipe (out): %w", err)
}
defer func() {
if err != nil {
_ = windows.CloseHandle(outRead)
}
}()
// CreatePseudoConsole dupes the handles it needs internally; we release
// our references to the child-side ends immediately after.
//
// It also spawns the conhost.exe serving the console session, as a
// 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.HandleView on GitHub (pinned to c477a2959b)
Solutions
- Free resources: close other PTY-backed processes and retry.
- Restart lazygit to reset any accumulated handle leaks.
- Check for external limiters (job objects, AV/EDR hooking pipe syscalls) if reproducible.
Defensive patterns
Strategy: fallback
Try / catch
sp, err := oscommands.StartPty(cmd, cols, rows)
if err != nil && strings.Contains(err.Error(), "CreatePipe") {
// second pipe failed: resources tight; fall back to non-PTY execution
return runWithoutPty(cmd)
} Prevention
- Serialize PTY startups to avoid racing many pipe creations at once.
- Monitor handle usage in long sessions; restart on growth.
- Ship a non-PTY code path so interactive features degrade instead of failing.
When it happens
Trigger: windows.CreatePipe failing on the second call within the same StartPty invocation — resource exhaustion hit between the two pipe creations, or job-object handle caps.
Common situations: Handle pressure during bursts of interactive-command spawning; long-running sessions; sandboxed environments.
Related errors
AI-assisted analysis of jesseduffield/lazygit@c477a2959b (2026-08-15).
Data as JSON: /api/errors/2aa6b535598f0086.
Report an issue: GitHub.