{"record":{"id":"2668213149669e0a","repo":"larksuite/cli","slug":"expected-hello-ack-got-t","errorCode":null,"errorMessage":"expected hello_ack, got %T","messagePattern":"expected hello_ack, got %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/event/consume/handshake.go","lineNumber":43,"sourceCode":"\t}\n\n\tif err := conn.SetReadDeadline(time.Now().Add(helloAckTimeout)); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"set hello_ack deadline: %w\", err)\n\t}\n\tbr := bufio.NewReader(conn)\n\tline, err := protocol.ReadFrame(br)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"no hello_ack received: %w\", err)\n\t}\n\t// best-effort clear; if the conn is already broken, the loop's first read will surface it\n\t_ = conn.SetReadDeadline(time.Time{})\n\tmsg, err := protocol.Decode(bytes.TrimRight(line, \"\\n\"))\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tack, ok := msg.(*protocol.HelloAck)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"expected hello_ack, got %T\", msg)\n\t}\n\treturn ack, br, nil\n}\n","sourceCodeStart":25,"sourceCodeEnd":47,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/event/consume/handshake.go#L25-L47","documentation":"doHello decoded the first frame from the server successfully, but it was not a *protocol.HelloAck. The library throws this because the handshake contract requires the immediate response to a Hello to be a HelloAck; any other message type means the peer is misbehaving or speaking a different protocol, so the connection is rejected with this type-mismatch error.","triggerScenarios":"protocol.Decode succeeds but the resulting message fails the *protocol.HelloAck type assertion in doHello (internal/event/consume/handshake.go:41-44) — e.g. the server sent an error frame, a Hello (server-initiated), a ping/pong, or a differently-versioned ack struct that decodes to another concrete type.","commonSituations":"Client and server protocol versions are out of sync (server replies with a new message type the old client decodes as something else); connected to the wrong service that sends a greeting/banner first; server pushes an error/reject message instead of the ack; middleware (auth proxy) injects its own first frame.","solutions":["Align client and server protocol versions — upgrade the client (or server) so the ack type matches protocol.HelloAck.","Log the decoded message content (%T plus payload) server-side to see what frame is actually being sent first.","Confirm the endpoint is the event bus itself, not a proxy/banner-emitting service on the same port.","If the server intentionally sends an error frame on rejection, surface that frame's payload to the caller instead of just the Go type."],"exampleFix":"// before: only exact HelloAck accepted\nack, ok := msg.(*protocol.HelloAck)\nif !ok { return nil, nil, fmt.Errorf(\"expected hello_ack, got %T\", msg) }\n// after: also recognize a typed rejection frame for a clearer failure\nswitch m := msg.(type) {\ncase *protocol.HelloAck:\n    ack = m\ncase *protocol.Error:\n    return nil, nil, fmt.Errorf(\"handshake rejected: %s\", m.Message)\ndefault:\n    return nil, nil, fmt.Errorf(\"expected hello_ack, got %T\", msg)\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isHelloAck(msg protocol.Message) (*protocol.HelloAck, bool) {\n    ack, ok := msg.(*protocol.HelloAck)\n    return ack, ok\n}","tryCatchPattern":"ack, br, err := doHello(conn, key, types, subID)\nif err != nil {\n    if strings.Contains(err.Error(), \"expected hello_ack, got \") {\n        log.Errorf(\"peer spoke unexpected first frame: %v — check protocol versions/endpoint\", err)\n    }\n    conn.Close()\n    return err\n}","preventionTips":["Pin and verify protocol version ('v1') on both client and server before deploy.","Never point the consumer at a non-bus endpoint that emits a greeting frame.","Add integration tests that assert the server's first reply decodes to *protocol.HelloAck."],"tags":["protocol","handshake","type-mismatch","versioning"],"backgroundTag":"unexpected-message-type","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}