kovidgoyal/kitty · error
Failed to connect to %s:%s with error: %w
Error message
Failed to connect to %s:%s with error: %w
What it means
net.Dial failed while connecting to the target network/address. The underlying error (wrapped with %w) says whether it was DNS resolution, connection refused, timeout, or network unreachable. This is the standard TCP/Unix dial failure path when fd passthrough mode is not in use.
Source
Thrown at tools/cmd/at/socket_io.go:180
func do_socket_io(io_data *rc_io_data) (serialized_response []byte, err error) {
var conn net.Conn
if global_options.to_network == "fd" {
fd, _ := strconv.Atoi(global_options.to_address)
if err != nil {
return nil, err
}
f := os.NewFile(uintptr(fd), "fd:"+global_options.to_address)
conn, err = net.FileConn(f)
if err != nil {
return nil, fmt.Errorf("Failed to open a socket for the remote control file descriptor: %d with error: %w", fd, err)
}
defer f.Close()
} else {
network := utils.IfElse(global_options.to_network == "ip", "tcp", global_options.to_network)
conn, err = net.Dial(network, global_options.to_address)
if err != nil {
err = fmt.Errorf("Failed to connect to %s:%s with error: %w", network, global_options.to_address, err)
return
}
}
defer conn.Close()
return simple_socket_io(&conn, io_data)
}
View on GitHub (pinned to 6d5d0c4406)
Solutions
- Check the wrapped error: 'connection refused' means nothing is listening — start the peer or fix the port; 'no such host' means fix DNS; 'i/o timeout' means firewall/routing
- Verify the address format matches the network (host:port for tcp/ip, path for unix)
- Test reachability with nc/curl or telnet to the same address
- If it's a startup-order issue, retry with backoff or add a readiness check before dialing
Example fix
# before at --to ip:myhost:9999 # after: confirm listener is up first ss -ltnp | grep 9999 # then retry, or use the exact host:port it shows at --to ip:127.0.0.1:9999
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: is anything listening?
if _, err := net.DialTimeout("tcp", addr, 2*time.Second); err != nil {
log.Fatalf("peer %s unreachable: %v", addr, err)
} Try / catch
var conn net.Conn
for attempt := 0; attempt < 5; attempt++ {
conn, err = doSocketIO(opts)
if err == nil { break }
if !isTemporary(err) { break } // refused/timeout -> retry; DNS error -> fail fast
time.Sleep(time.Duration(attempt+1) * 500 * time.Millisecond)
} Prevention
- Start listeners before dialers, or add readiness checks in startup scripts
- Wrap dials with net.DialTimeout instead of unbounded waits
- Use errors.Is/As on the wrapped error to distinguish refused vs timeout vs DNS
When it happens
Trigger: Calling do_socket_io with to_network 'ip' (mapped to tcp) or another network and an address nothing is listening on, a hostname that doesn't resolve, a firewall dropping SYN packets (timeout), or the listener process not yet started.
Common situations: Service not started yet, wrong port in config, DNS pointing at a dead host, firewall/VPN blocking the port, or IPv6/IPv4 mismatch between resolved address and listener binding.
Related errors
- Did not receive expected streaming response
- Too much piped data
- Canceled by user
- Execute command
- No lexer available for this format
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/f0d8a72dabfd8887.
Report an issue: GitHub.