kovidgoyal/kitty · error

failed to upload , SSH master process died

Error message

failed to upload %s, SSH master process died

What it means

After the local editor exits, edit_loop checks that the SSH ControlMaster process is still running via IsAlive(); if it died (crashed or exited), the edited file cannot be uploaded and this error is returned with the remote path. No upload is attempted.

Solutions

  1. Reconnect ssh and rerun the remote file edit; local changes are safe
  2. Configure ssh ClientAliveInterval / ServerAliveInterval to keep the master alive
  3. Check whether the master exited due to network failure or an ssh error (master's log)
  4. Consider shorter edit sessions or re-upload manually via scp
Defensive patterns

Strategy: fallback

Validate before calling

if !master.IsAlive() { /* re-establish master before upload */ }

Try / catch

if err != nil && strings.Contains(err.Error(), "master process died") {
    // reconnect ssh and re-upload local copy
}

Prevention

When it happens

Trigger: handle_action edit flow where the ssh master process exits during the editing session (network drop, ssh crash, server-side disconnect).

Common situations: Long editing sessions that outlive an idle/disconnected ssh multiplex master, network changes (WiFi switch, VPN drop), or ssh server killing idle connections.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/d0fad4aa625513d7. Report an issue: GitHub.

Appendix: source

Thrown at kittens/remote_file/actions.go:192

	argv := append(append([]string{}, editor...), master.Dest)
	cmd := exec.Command(argv[0], argv[1:]...)
	cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
	if err := cmd.Start(); err != nil {
		return err
	}
	done := make(chan error, 1)
	go func() { done <- cmd.Wait() }()
	for {
		select {
		case <-done:
			reset_terminal()
			if master.IsAlive() {
				if err := master.Upload(false); err != nil {
					return fmt.Errorf("failed to upload %s: %w", master.remote_path, err)
				}
				return nil
			}
			return fmt.Errorf("failed to upload %s, SSH master process died", master.remote_path)
		case <-time.After(100 * time.Millisecond):
			if st, err := os.Stat(master.Dest); err == nil && st.ModTime().After(mtime) {
				mtime = st.ModTime()
				if master.IsAlive() {
					_ = master.Upload(true)
				}
			}
		}
	}
}

View on GitHub (pinned to 6d5d0c4406)