jesseduffield/lazygit · error

Update failed: {{.errMessage}}

Error message

Update failed: {{.errMessage}}

What it means

Produced by UpdateHelper.onUpdateFinish after the self-update subprocess fails: the raw updater error is wrapped into the UpdateFailedErr template ('Update failed: {{.errMessage}}') and shown on the UI thread after clearing the status view and flipping the updating flag off. It is a terminal report of a failed binary replacement — no retry is scheduled.

Source

Thrown at pkg/gui/controllers/helpers/update_helper.go:76

func (self *UpdateHelper) startUpdating(newVersion string) {
	_ = self.c.WithWaitingStatus(self.c.Tr.UpdateInProgressWaitingStatus, func(gocui.Task) error {
		self.c.State().SetUpdating(true)
		err := self.updater.Update(newVersion)
		return self.onUpdateFinish(err)
	})
}

func (self *UpdateHelper) onUpdateFinish(err error) error {
	self.c.State().SetUpdating(false)
	self.c.OnUIThread(func() error {
		self.c.SetViewContent(self.c.Views().AppStatus, "")
		if err != nil {
			errMessage := utils.ResolvePlaceholderString(
				self.c.Tr.UpdateFailedErr, map[string]string{
					"errMessage": err.Error(),
				},
			)
			return errors.New(errMessage)
		}
		self.c.Alert(self.c.Tr.UpdateCompletedTitle, self.c.Tr.UpdateCompleted)
		return nil
	})

	return nil
}

func (self *UpdateHelper) showUpdatePrompt(newVersion string) error {
	message := utils.ResolvePlaceholderString(
		self.c.Tr.UpdateAvailable, map[string]string{
			"newVersion": newVersion,
		},
	)

	self.c.Confirm(types.ConfirmOpts{
		Title:  self.c.Tr.UpdateAvailableTitle,
		Prompt: message,

View on GitHub (pinned to c477a2959b)

Solutions

  1. Check the embedded errMessage — it names the concrete cause (permissions, 404 asset, checksum).
  2. If the binary is package-manager owned, update via that package manager and disable in-app updates.
  3. For permission issues, update manually: download the release tarball and replace the binary in a PATH dir you own (~/.local/bin).
  4. Retry on a stable network if the failure was a truncated download.
Defensive patterns

Strategy: try-catch

Validate before calling

// before updating, confirm the binary is replaceable:
if info, err := os.Stat(os.Executable()); err != nil || info.Mode().Perm()&0o200 == 0 {
    // update manually instead of in-app self-update
}

Try / catch

err := updater.Update(newVersion)
if err != nil {
    // err.Error() already carries the root cause inside UpdateFailedErr;
    // branch on it: permissions -> manual update, network -> retry once
}

Prevention

When it happens

Trigger: Accepting the update prompt and the download/verify/replace step failing: no write permission on the running binary, download interrupted, checksum verification failure, or an unsupported platform/release-asset layout.

Common situations: lazygit installed to a root-owned or package-manager-owned path (/usr/bin, /opt/homebrew owned by brew) so replacing the binary fails; corporate proxies truncating downloads; running from a read-only mount (NFS, snap confinement); version feed advertising an asset missing for the OS/arch.

Related errors


AI-assisted analysis of jesseduffield/lazygit@c477a2959b (2026-08-15). Data as JSON: /api/errors/262055f1d8ffb079. Report an issue: GitHub.