{"record":{"id":"4a285b052f6d8992","repo":"gastownhall/beads","slug":"identity-dial-control-listener-w","errorCode":null,"errorMessage":"identity: dial control listener: %w","messagePattern":"identity: dial control listener: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/identity/control.go","lineNumber":45,"sourceCode":"// IdentReply is the authenticated identity published by a managed proxy.\ntype IdentReply struct {\n\tSchema      int    `json:\"schema\"`\n\tRole        string `json:\"role\"`\n\tRootID      string `json:\"root_id\"`\n\tUpstreamID  string `json:\"upstream_id\"`\n\tPID         int    `json:\"pid\"`\n\tBirth       string `json:\"birth\"`\n\tDataPort    int    `json:\"data_port\"`\n\tControlPort int    `json:\"control_port\"`\n\tMAC         string `json:\"mac\"`\n}\n\n// Identify authenticates to a proxy control listener and returns its identity.\nfunc Identify(host string, controlPort int, secret string, timeout time.Duration) (*IdentReply, error) {\n\taddr := net.JoinHostPort(host, strconv.Itoa(controlPort))\n\tconn, err := net.DialTimeout(\"tcp\", addr, timeout)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"identity: dial control listener: %w\", err)\n\t}\n\tdefer func() { _ = conn.Close() }()\n\n\tif err := conn.SetDeadline(time.Now().Add(timeout)); err != nil {\n\t\treturn nil, fmt.Errorf(\"identity: set control deadline: %w\", err)\n\t}\n\tnonceBytes := make([]byte, identNonceBytes)\n\tif _, err := rand.Read(nonceBytes); err != nil {\n\t\treturn nil, fmt.Errorf(\"identity: generate request nonce: %w\", err)\n\t}\n\tnonce := hex.EncodeToString(nonceBytes)\n\tif _, err := io.WriteString(conn, \"IDENT \"+secret+\" \"+nonce+\"\\n\"); err != nil {\n\t\treturn nil, fmt.Errorf(\"identity: write request: %w\", err)\n\t}\n\n\tline, err := bufio.NewReader(io.LimitReader(conn, maxIdentReplyBytes+1)).ReadString('\\n')\n\tif errors.Is(err, io.EOF) && len(line) == 0 {\n\t\treturn nil, ErrIdentRefused","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/identity/control.go#L27-L63","documentation":"Identify dials the dbproxy control TCP listener to authenticate and fetch the proxy's identity. This error wraps net.DialTimeout's failure — the TCP connection to host:controlPort could not be established.","triggerScenarios":"Calling identity.Identify(host, controlPort, secret, timeout) when the control listener is not running, the port is wrong, the host is unreachable, or a firewall blocks the connection.","commonSituations":"Proxy daemon not started yet; stale/wrong control port from config; connecting from another container/network namespace; DNS resolving to the wrong interface; firewall dropping the port.","solutions":["Verify the proxy control listener is running and note its actual control port","Confirm host and controlPort match the proxy's startup logs/config","Test reachability with nc -vz host controlPort","Check firewall/security-group rules for the control port"],"exampleFix":"// before\nreply, err := Identify(\"localhost\", 42881, secret, 2*time.Second) // port guess\n// after\nreply, err := Identify(\"localhost\", proxy.ControlPort(), secret, 5*time.Second)","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", net.JoinHostPort(host, strconv.Itoa(controlPort)), timeout)\nif err != nil { /* surface actionable message before calling Identify */ }","typeGuard":null,"tryCatchPattern":"reply, err := Identify(host, port, secret, timeout)\nif errors.Is(err, syscall.ECONNREFUSED) || strings.Contains(err.Error(), \"dial control listener\") {\n\t// wait for the proxy to start and retry with backoff\n}","preventionTips":["Wait for the proxy's ready signal before calling Identify","Read the control port from the proxy's runtime state, not a hardcoded value","Verify network/firewall reachability of the control port in CI"],"tags":["network","tcp","dial","dbproxy"],"backgroundTag":"connection-refused","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}