{"record":{"id":"b3fc3997be8495e5","repo":"jesseduffield/lazygit","slug":"dynamic-stderr-of-failed-command","errorCode":null,"errorMessage":"<dynamic: stderr of failed command>","messagePattern":"<dynamic: stderr of failed command>","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/oscommands/cmd_obj_runner.go","lineNumber":313,"sourceCode":"\t// so close it to unblock the reader — the pipe is synchronous, so all\n\t// output has already been read by now and nothing is lost.\n\tif !cmdObj.ShouldUsePty() {\n\t\tif closeErr := handler.close(); closeErr != nil {\n\t\t\tself.log.Error(closeErr)\n\t\t}\n\t}\n\t<-streamingDone\n\n\tself.log.Infof(\"%s (%s)\", cmdObj.ToString(), time.Since(t))\n\n\tif err != nil {\n\t\tif cmdObj.suppressOutputUnlessError {\n\t\t\t_, _ = self.guiIO.newCmdWriterFn().Write(combinedOutput.Bytes())\n\t\t}\n\n\t\terrStr := stderr.String()\n\t\tif errStr != \"\" {\n\t\t\treturn errors.New(errStr)\n\t\t}\n\n\t\tif cmdObj.ShouldIgnoreEmptyError() {\n\t\t\treturn nil\n\t\t}\n\t\tstdoutStr := stdout.String()\n\t\tif stdoutStr != \"\" {\n\t\t\treturn errors.New(stdoutStr)\n\t\t}\n\t\treturn errors.New(\"Command exited with non-zero exit code, but no output\")\n\t}\n\n\treturn nil\n}\n\ntype CredentialType int\n\nconst (","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/jesseduffield/lazygit/blob/c477a2959b229fbf3284be0d4d2904ab61ec3c94/pkg/commands/oscommands/cmd_obj_runner.go#L295-L331","documentation":"Returned from the streaming command runner in pkg/commands/oscommands/cmd_obj_runner.go:313. After a command run via RunCommandOutputWithInlineStatus-style streaming fails, lazygit checks the captured stderr buffer first; if stderr is non-empty it becomes the error. This prioritizes the most diagnostic channel for failed git commands.","triggerScenarios":"Running a CmdObj with streamed output (e.g. inline-status tasks like fetch/pull/push/fast-forward) where the process exits non-zero and wrote to stderr. The stderr string is returned verbatim as errors.New(errStr).","commonSituations":"git pull with merge conflicts signaled on stderr, push rejected (non-fast-forward), ssh authentication prompts failing, credential helper errors during a streamed operation.","solutions":["Read the returned error string — it is the exact stderr of the git command","Correct the underlying git state (commit/divergent branches, credentials, remote config)","If suppressOutputUnlessError was set, the combined output was already flushed to the UI; check the lazygit command log for the full command line","For scripted use, run the same git command manually to reproduce"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := task.Run(func() error {\n    return self.c.OS().Cmd.New(args).Run()\n}); err != nil {\n    if strings.Contains(err.Error(), \"Authentication failed\") {\n        return self.promptForCredentials()\n    }\n    return err // err.Error() is the command's stderr\n}","preventionTips":["Treat the error text as the diagnostic source; it is verbatim stderr","Handle specific failure phrases only as a UX nicety, never for control-critical logic","Reproduce failed streamed commands in a terminal before changing config"],"tags":["git","subprocess","stderr","streaming"],"backgroundTag":null,"analyzedSha":"c477a2959b229fbf3284be0d4d2904ab61ec3c94","analyzedAt":"2026-08-15T08:34:32.451Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}