kovidgoyal/kitty · error

Invalid KITTY_PID env var not an integer: %#v

Error message

Invalid KITTY_PID env var not an integer: %#v

What it means

With ShareConnections enabled the kitten builds ssh ControlMaster arguments keyed by the parent kitty PID, reading KITTY_PID from the environment. strconv.Atoi failed, so the variable is missing/empty or non-numeric and connection sharing cannot be set up.

Source

Thrown at kittens/ssh/main.go:677

	}
	if len(bad_lines) > 0 {
		for _, x := range bad_lines {
			fmt.Fprintf(os.Stderr, "Ignoring bad config line: %s:%d with error: %s", filepath.Base(x.Src_file), x.Line_number, x.Err)
		}
	}
	if host_opts.Delegate != "" {
		delegate_cmd, err := shlex.Split(host_opts.Delegate)
		if err != nil {
			return 1, fmt.Errorf("Could not parse delegate command: %#v with error: %w", host_opts.Delegate, err)
		}
		return 1, unix.Exec(utils.FindExe(delegate_cmd[0]), utils.Concat(delegate_cmd, ssh_args, server_args), os.Environ())
	}
	master_is_alive, master_checked := false, false
	var control_master_args []string
	if host_opts.Share_connections {
		kpid, err := strconv.Atoi(os.Getenv("KITTY_PID"))
		if err != nil {
			return 1, fmt.Errorf("Invalid KITTY_PID env var not an integer: %#v", os.Getenv("KITTY_PID"))
		}
		control_master_args, err = connection_sharing_args(kpid)
		if err != nil {
			return 1, err
		}
		cmd = slices.Insert(cmd, insertion_point, control_master_args...)
	}
	use_kitty_askpass := host_opts.Askpass == Askpass_native || (host_opts.Askpass == Askpass_unless_set && os.Getenv("SSH_ASKPASS") == "")
	need_to_request_data := true
	if use_kitty_askpass {
		need_to_request_data = set_askpass(hostname_for_match, uname, overrides)
	}
	master_is_functional := func() bool {
		if master_checked {
			return master_is_alive
		}
		master_checked = true
		// slices.Insert can mutate cmd's backing array in place; clone so cmd stays intact

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Run the kitten from inside a kitty window so KITTY_PID is set by the terminal
  2. Verify: echo $KITTY_PID inside the same shell before invoking
  3. Disable Share_connections for that host in ssh.conf if you must run outside kitty
  4. Fix wrappers/scripts that scrub the environment (remove KITTY_PID from any unset list)

Example fix

# before (from a non-kitty terminal)
kitty +kitten ssh user@host   # with share_connections yes
# after
# inside kitty:
kitty +kitten ssh user@host
# or in ssh.conf for that host:
share_connections no
Defensive patterns

Strategy: validation

Validate before calling

if pid, err := strconv.Atoi(os.Getenv("KITTY_PID")); err != nil || os.Getenv("KITTY_PID") == "" {
    // disable share_connections or bail with a clear message
}

Type guard

func insideKitty() bool {
    p := os.Getenv("KITTY_PID")
    _, err := strconv.Atoi(p)
    return err == nil && p != ""
}

Try / catch

if _, err := run_ssh(...); err != nil && strings.Contains(err.Error(), "KITTY_PID") {
    // rerun without connection sharing
}

Prevention

When it happens

Trigger: run_ssh with host_opts.ShareConnections true while KITTY_PID is unset, empty, or contains non-digits — typically when the kitten is exec'd outside a kitty terminal or the env var was stripped.

Common situations: Running kitty +kitten ssh from a plain xterm/SSH session or cron/systemd; env -i or sanitizing wrappers dropping KITTY_PID; wrappers like env WORDSIZE changing the variable; older/newer kitty version mismatch between launcher and kitten.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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