larksuite/cli · error
no hello_ack received: %w
Error message
no hello_ack received: %w
What it means
After installing the 5s read deadline, doHello reads the hello_ack frame with protocol.ReadFrame; this error wraps any read failure — most commonly the 5-second helloAckTimeout expiring (i/o timeout) or the connection closing before any ack arrived. The library throws it because a Hello without a HelloAck means the server did not accept the subscription handshake, so the event stream cannot start.
Source
Thrown at internal/event/consume/handshake.go:33
)
const helloAckTimeout = 5 * time.Second // symmetric with bus-side hello read deadline
// doHello returns a bufio.Reader holding any bytes already pulled off conn so events
// buffered with the ack in one TCP segment aren't dropped.
func doHello(conn net.Conn, eventKey string, eventTypes []string, subscriptionID string) (*protocol.HelloAck, *bufio.Reader, error) {
hello := protocol.NewHello(os.Getpid(), eventKey, eventTypes, "v1", subscriptionID)
if err := protocol.EncodeWithDeadline(conn, hello, protocol.WriteTimeout); err != nil {
return nil, nil, err
}
if err := conn.SetReadDeadline(time.Now().Add(helloAckTimeout)); err != nil {
return nil, nil, fmt.Errorf("set hello_ack deadline: %w", err)
}
br := bufio.NewReader(conn)
line, err := protocol.ReadFrame(br)
if err != nil {
return nil, nil, fmt.Errorf("no hello_ack received: %w", err)
}
// best-effort clear; if the conn is already broken, the loop's first read will surface it
_ = conn.SetReadDeadline(time.Time{})
msg, err := protocol.Decode(bytes.TrimRight(line, "\n"))
if err != nil {
return nil, nil, err
}
ack, ok := msg.(*protocol.HelloAck)
if !ok {
return nil, nil, fmt.Errorf("expected hello_ack, got %T", msg)
}
return ack, br, nil
}
View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Retry with backoff: Run's reconnect loop should redial — a timeout is often transient (server restart or load).
- Verify the dial address points at the correct event-bus host/port that speaks this frame protocol.
- Check server health/logs at the timestamp to see whether the Hello arrived and why no ack was emitted.
- Inspect protocol compatibility: client and server must agree on frame encoding and hello_ack shape (protocol version 'v1').
- If timeouts are frequent, investigate network latency/keepalive between client and bus.
Example fix
// before: single attempt, hard fail
ack, br, err := doHello(conn, eventKey, eventTypes, subID)
if err != nil { return err }
// after: let Run's reconnect loop retry transient handshake failures
if err := backoff.Retry(ctx, func() error {
_, err := runOnce(ctx)
return err
}); err != nil { return err } Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", addr, 3*time.Second)
if err != nil {
return fmt.Errorf("event bus unreachable at %s: %w", addr, err)
} Type guard
func isHelloAckTimeout(err error) bool {
var ne net.Error
return errors.As(err, &ne) && ne.Timeout()
} Try / catch
if _, _, err := doHello(conn, key, types, subID); err != nil {
if isHelloAckTimeout(err) {
conn.Close()
return backoffRetry(ctx) // transient: server slow or restarting
}
return err // non-timeout read failure: surface to caller
} Prevention
- Deploy Run with a reconnect/backoff loop so 5s ack timeouts self-heal.
- Health-check the bus endpoint before dialing in ops scripts.
- Keep client and server frame-protocol versions in lockstep.
- Alert on handshake failure rate to catch bus outages early.
When it happens
Trigger: protocol.ReadFrame(br) returns an error after a Hello frame was sent on the conn: server never replied within helloAckTimeout (5s), server closed the TCP connection, or sent a malformed/oversized frame that the framer rejects.
Common situations: Event bus is down or overloaded and not answering handshakes; wrong endpoint/port (connected to something that is not the bus); server rejected the connection silently after Hello; network partition or TLS/proxy stripping the stream; server version speaks a different frame protocol.
Related errors
- set hello_ack deadline: %w
- lark-cli timed out after {timeout}s
- poll network error: %w
- npm install timed out after %s
- pnpm install timed out after %s
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/172fca0652946f18.
Report an issue: GitHub.