{"record":{"id":"3aef7be4bee34c94","repo":"kovidgoyal/kitty","slug":"failed-to-open-a-socket-for-the-remote-control-fil","errorCode":null,"errorMessage":"Failed to open a socket for the remote control file descriptor: %d with error: %w","messagePattern":"Failed to open a socket for the remote control file descriptor: (.+?) with error: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/cmd/at/socket_io.go","lineNumber":173,"sourceCode":"\t\t}\n\t}\n\tif io_data.rc.NoResponse {\n\t\treturn\n\t}\n\treturn r.read_response_from_conn(conn, io_data.timeout)\n}\n\nfunc do_socket_io(io_data *rc_io_data) (serialized_response []byte, err error) {\n\tvar conn net.Conn\n\tif global_options.to_network == \"fd\" {\n\t\tfd, _ := strconv.Atoi(global_options.to_address)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tf := os.NewFile(uintptr(fd), \"fd:\"+global_options.to_address)\n\t\tconn, err = net.FileConn(f)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"Failed to open a socket for the remote control file descriptor: %d with error: %w\", fd, err)\n\t\t}\n\t\tdefer f.Close()\n\t} else {\n\t\tnetwork := utils.IfElse(global_options.to_network == \"ip\", \"tcp\", global_options.to_network)\n\t\tconn, err = net.Dial(network, global_options.to_address)\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"Failed to connect to %s:%s with error: %w\", network, global_options.to_address, err)\n\t\t\treturn\n\t\t}\n\t}\n\tdefer conn.Close()\n\treturn simple_socket_io(&conn, io_data)\n}\n","sourceCodeStart":155,"sourceCodeEnd":187,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/tools/cmd/at/socket_io.go#L155-L187","documentation":"do_socket_io was given a remote control file descriptor (fd passthrough mode instead of dialing an address). os.NewFile succeeded but net.FileConn failed, meaning the inherited fd is not a usable socket conn. This typically happens when the fd number is wrong or the descriptor was already consumed/closed.","triggerScenarios":"Running the at tool under a supervisor that passes a socket via fd inheritance (e.g. systemd socket activation) when the fd number in global_options doesn't correspond to a live socket, or the Go runtime already took ownership of that fd via another os.NewFile call (double-claim causes 'file already closed' style errors).","commonSituations":"Misconfigured systemd socket-activation FD name/number, fd offset off-by-one, or code elsewhere in the process calling os.NewFile on the same descriptor first, invalidating it.","solutions":["Verify the fd number being passed matches the FD the supervisor actually allocated (check $LISTEN_FDS, systemd socket files)","Ensure os.NewFile is called exactly once per descriptor; duplicate claims invalidate the fd","Check that the socket unit type matches (stream vs datagram) what FileConn expects","Fall back to explicit net.Dial addressing instead of fd passthrough while debugging"],"exampleFix":"// before\nf := os.NewFile(uintptr(fd), \"fd:\"+global_options.to_address)\nconn, err = net.FileConn(f)\n// after: guard double-claim and verify fd is live\nif fd <= 0 { return nil, fmt.Errorf(\"invalid fd %d\", fd) }\nf := os.NewFile(uintptr(fd), \"fd:\"+global_options.to_address)\nconn, err = net.FileConn(f)\nif err != nil { return nil, fmt.Errorf(\"fd %d not a socket: %w\", fd, err) }","handlingStrategy":"try-catch","validationCode":"// Before FileConn: verify the fd refers to a live socket\nvar st unix.Stat_t\nif err := unix.Fstat(fd, &st); err != nil {\n    return fmt.Errorf(\"fd %d unusable: %w\", fd, err)\n}","typeGuard":null,"tryCatchPattern":"conn, err := do_socket_io(...)\nif err != nil && strings.Contains(err.Error(), \"Failed to open a socket for the remote control file descriptor\") {\n    // fall back to explicit dial instead of fd passthrough\n    conn, err = net.Dial(\"tcp\", explicitAddr)\n}","preventionTips":["Claim each inherited fd with os.NewFile exactly once","Validate supervisor fd numbers (LISTEN_FDS / socket units) in smoke tests","Keep an explicit-address fallback path for environments without fd passing"],"tags":["file-descriptor","systemd","socket-activation","go"],"backgroundTag":"invalid-file-descriptor","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}