chenhg5/cc-connect · error
expected op 10 (Hello), got op %d
Error message
expected op 10 (Hello), got op %d
What it means
Returned when the first frame received on the WebSocket is not an op 10 (Hello) dispatch, indicating the server deviated from the QQ gateway protocol. Usually the connection is being rejected or a different op (e.g. an error/close op) arrives first.
Source
Thrown at platform/qqbot/qqbot.go:726
}
type wsPayload struct {
Op int `json:"op"`
D json.RawMessage `json:"d,omitempty"`
S *int64 `json:"s,omitempty"`
T string `json:"t,omitempty"`
}
func (p *Platform) waitForHello(conn *websocket.Conn) error {
_ = conn.SetReadDeadline(time.Now().Add(15 * time.Second))
defer func() { _ = conn.SetReadDeadline(time.Time{}) }()
var msg wsPayload
if err := conn.ReadJSON(&msg); err != nil {
return fmt.Errorf("waiting for hello: %w", err)
}
if msg.Op != opHello {
return fmt.Errorf("expected op 10 (Hello), got op %d", msg.Op)
}
var hello struct {
HeartbeatInterval int `json:"heartbeat_interval"`
}
if err := json.Unmarshal(msg.D, &hello); err != nil {
slog.Warn("qqbot: failed to parse Hello payload", "error", err)
}
if hello.HeartbeatInterval > 0 {
p.heartbeatMs = hello.HeartbeatInterval
} else {
p.heartbeatMs = 41250 // sane default
}
p.heartbeatOK.Store(true)
slog.Debug("qqbot: received Hello", "heartbeat_interval", p.heartbeatMs)
return nil
}View on GitHub (pinned to 4000b2338a)
Solutions
- Log msg.Op and msg.D of the unexpected frame to identify what the server sent
- Refresh the access token and reconnect — invalid auth often surfaces as a wrong-op frame
- Update to the latest QQ gateway protocol expectations (op codes) if QQ changed them
- Retry; if op indicates reconnect, honor the resume flow instead of failing
Example fix
// before
if msg.Op != opHello {
return fmt.Errorf("expected op 10 (Hello), got op %d", msg.Op)
}
// after
if msg.Op != opHello {
return fmt.Errorf("expected op 10 (Hello), got op %d payload=%s", msg.Op, msg.D)
} Defensive patterns
Strategy: try-catch
Type guard
func isHelloFrame(msg wsPayload) bool { return msg.Op == opHello } Try / catch
if err := p.waitForHello(conn); err != nil {
if strings.Contains(err.Error(), "got op") {
slog.Error("unexpected hello frame, reconnecting", "err", err)
return p.reconnect()
}
return err
} Prevention
- Track QQ gateway protocol updates
- Log the raw frame payload for every unexpected op
- Validate tokens before connecting so rejections surface early
When it happens
Trigger: After dialing, the server sends a frame whose op code is not opHello — e.g. op 9 (invalid session), an error payload, or a reconnect request instead of Hello.
Common situations: QQ protocol/API version drift; connecting with an invalid token causing a non-Hello rejection frame; running an outdated bot SDK against a changed gateway.
Related errors
- expected READY event, got op=%d t=%s
- cloud_web: expected register_ack, got %q
- waiting for hello: %w
- waiting for ready: %w
- codex app-server initialize: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/b9ed23f4f3552842.
Report an issue: GitHub.