kovidgoyal/kitty · error

invalid --ssh-connection-data: %w

Error message

invalid --ssh-connection-data: %w

What it means

parse_conn_data JSON-decodes the --ssh-connection-data argument (a JSON array). This variant fires when json.Unmarshal fails, i.e. the argument is not valid JSON at all. It is called by handle_action and exercised by tests.

Source

Thrown at kittens/remote_file/ssh.go:28

	"strings"
)

// Must match kittens/remote_file/main.py is_ssh_kitten_sentinel
const is_ssh_kitten_sentinel = `!#*&$#($ssh-kitten)(##$`

type SSHConnectionData struct {
	Binary           string
	Hostname         string
	Port             int
	IdentityFile     string
	IsSSHKitten      bool
	SSHKittenCmdline []string
}

func parse_conn_data(raw string) (*SSHConnectionData, error) {
	var items []any
	if err := json.Unmarshal([]byte(raw), &items); err != nil {
		return nil, fmt.Errorf("invalid --ssh-connection-data: %w", err)
	}
	if len(items) < 2 {
		return nil, fmt.Errorf("invalid --ssh-connection-data: need at least binary and hostname")
	}
	first, _ := items[0].(string)
	ans := &SSHConnectionData{}
	if first == is_ssh_kitten_sentinel {
		// Python: SSHConnectionData(sentinel, cli_data[-1], -1, identity_file=json.dumps(cli_data[1:]))
		// with the cmdline stripped of -t flags and its last two items.
		ans.IsSSHKitten = true
		ans.Hostname, _ = items[len(items)-1].(string)
		cmdline := make([]string, 0, len(items)-1)
		for _, x := range items[1:] {
			s, _ := x.(string)
			if s != "-t" {
				cmdline = append(cmdline, s)
			}
		}

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Validate the argument with a JSON linter before passing it
  2. Pass the array as proper JSON: ["/usr/bin/ssh","host"]
  3. Let kitty generate --ssh-connection-data rather than constructing it by hand
  4. In tests, build the JSON with json.Marshal instead of string concatenation

Example fix

// before
--ssh-connection-data '/usr/bin/ssh host'
// after
--ssh-connection-data '["/usr/bin/ssh","host"]'
Defensive patterns

Strategy: validation

Validate before calling

var items []any
if err := json.Unmarshal([]byte(raw), &items); err != nil { /* reject before calling */ }

Type guard

func isValidConnData(raw string) bool { var v []any; return json.Unmarshal([]byte(raw), &v) == nil }

Prevention

When it happens

Trigger: Passing --ssh-connection-data with malformed JSON: missing brackets, trailing commas, single quotes, or shell-quoting corruption of the array.

Common situations: Hand-writing or shell-escaping the argument incorrectly when invoking the remote_file kitten manually instead of letting kitty construct it.

Related errors


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