{"record":{"id":"2aa6b535598f0086","repo":"jesseduffield/lazygit","slug":"createpipe-out-w","errorCode":null,"errorMessage":"CreatePipe (out): %w","messagePattern":"CreatePipe \\(out\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/oscommands/pty_windows.go","lineNumber":290,"sourceCode":"\treturn h\n}\n\nfunc StartPty(cmd *exec.Cmd, cols, rows uint16) (sp StartedPty, err error) {\n\t// Two pipes: one for the child's stdin (we never write to it, but ConPTY\n\t// needs a handle), one for the child's stdout/stderr multiplexed through\n\t// the pseudoconsole.\n\tvar inRead, inWrite, outRead, outWrite windows.Handle\n\tif err = windows.CreatePipe(&inRead, &inWrite, nil, 0); err != nil {\n\t\treturn StartedPty{}, fmt.Errorf(\"CreatePipe (in): %w\", err)\n\t}\n\tdefer func() {\n\t\tif err != nil {\n\t\t\t_ = windows.CloseHandle(inWrite)\n\t\t}\n\t}()\n\tif err = windows.CreatePipe(&outRead, &outWrite, nil, 0); err != nil {\n\t\t_ = windows.CloseHandle(inRead)\n\t\treturn StartedPty{}, fmt.Errorf(\"CreatePipe (out): %w\", err)\n\t}\n\tdefer func() {\n\t\tif err != nil {\n\t\t\t_ = windows.CloseHandle(outRead)\n\t\t}\n\t}()\n\n\t// CreatePseudoConsole dupes the handles it needs internally; we release\n\t// our references to the child-side ends immediately after.\n\t//\n\t// It also spawns the conhost.exe serving the console session, as a\n\t// direct child of this process. The teardown in Close needs a handle to\n\t// that conhost (see there), but Windows offers no way to obtain one\n\t// from the HPCON, so identify it by diffing our conhost children around\n\t// the call. Open a real handle right away so that pid reuse can't later\n\t// misdirect the teardown's reap. If identification fails, the handle\n\t// stays 0 and the teardown skips the reap.\n\tvar hpc, conhost windows.Handle","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/jesseduffield/lazygit/blob/c477a2959b229fbf3284be0d4d2904ab61ec3c94/pkg/commands/oscommands/pty_windows.go#L272-L308","documentation":"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.","triggerScenarios":"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.","commonSituations":"Handle pressure during bursts of interactive-command spawning; long-running sessions; sandboxed environments.","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."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"sp, err := oscommands.StartPty(cmd, cols, rows)\nif err != nil && strings.Contains(err.Error(), \"CreatePipe\") {\n    // second pipe failed: resources tight; fall back to non-PTY execution\n    return runWithoutPty(cmd)\n}","preventionTips":["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."],"tags":["windows","pty","conpty","syscall","pipes"],"backgroundTag":null,"analyzedSha":"c477a2959b229fbf3284be0d4d2904ab61ec3c94","analyzedAt":"2026-08-15T08:34:32.451Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}