gastownhall/beads · error
identity: write request: %w
Error message
identity: write request: %w
What it means
Identify writes the IDENT request line (secret + nonce) to the control connection. This error wraps the io.WriteString failure, meaning the TCP write failed after dialing — the connection broke mid-handshake.
Source
Thrown at internal/storage/dbproxy/identity/control.go:58
// Identify authenticates to a proxy control listener and returns its identity.
func Identify(host string, controlPort int, secret string, timeout time.Duration) (*IdentReply, error) {
addr := net.JoinHostPort(host, strconv.Itoa(controlPort))
conn, err := net.DialTimeout("tcp", addr, timeout)
if err != nil {
return nil, fmt.Errorf("identity: dial control listener: %w", err)
}
defer func() { _ = conn.Close() }()
if err := conn.SetDeadline(time.Now().Add(timeout)); err != nil {
return nil, fmt.Errorf("identity: set control deadline: %w", err)
}
nonceBytes := make([]byte, identNonceBytes)
if _, err := rand.Read(nonceBytes); err != nil {
return nil, fmt.Errorf("identity: generate request nonce: %w", err)
}
nonce := hex.EncodeToString(nonceBytes)
if _, err := io.WriteString(conn, "IDENT "+secret+" "+nonce+"\n"); err != nil {
return nil, fmt.Errorf("identity: write request: %w", err)
}
line, err := bufio.NewReader(io.LimitReader(conn, maxIdentReplyBytes+1)).ReadString('\n')
if errors.Is(err, io.EOF) && len(line) == 0 {
return nil, ErrIdentRefused
}
if err != nil {
return nil, fmt.Errorf("identity: read reply: %w", err)
}
if len(line) > maxIdentReplyBytes {
return nil, errors.New("identity: oversized reply")
}
var reply IdentReply
if err := json.Unmarshal([]byte(line), &reply); err != nil {
return nil, fmt.Errorf("identity: decode reply: %w", err)
}
if err := VerifyIdentReply(reply, secret, nonce); err != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Confirm the port is actually the proxy's control listener speaking the IDENT protocol
- Increase the timeout so the write is not cut off
- Check proxy logs for a crash or early connection close
- Retry; if the listener is flapping, restart the proxy
Defensive patterns
Strategy: retry
Try / catch
reply, err := Identify(host, port, secret, timeout)
if err != nil && strings.Contains(err.Error(), "write request") {
// connection dropped mid-handshake; retry with backoff, check proxy health
} Prevention
- Point Identify at the real control listener, not another service
- Use a timeout generous enough to cover dial+write+read
- Watch proxy logs for crashes that close connections early
When it happens
Trigger: The control listener closed or reset the connection before/while the request was written; network drop between dial and write; write deadline already exceeded.
Common situations: Listener crashed or refused the connection immediately after accept; wrong service on the port that closes on unknown input; very tight timeout expiring between dial and write; intermediary firewall sending RST.
Related errors
- identity: dial control listener: %w
- ensureProxiedServerConfig: pick free port: %w
- allocating ephemeral port: %w
- identity: set control deadline: %w
- authenticated proxy data port %d is not accepting connection
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/67380cb9756839ed.
Report an issue: GitHub.