chenhg5/cc-connect · error
cloud_web: expected register_ack, got %q
Error message
cloud_web: expected register_ack, got %q
What it means
After successfully unmarshaling the register_ack frame, parseRegisterAck verifies the frame's type field equals "register_ack". If the server sent a different message type as the first frame after dialing, this error is thrown and the connection is closed. It indicates a protocol sequencing problem: the peer spoke first with something other than the expected registration acknowledgment.
Source
Thrown at platform/cloud-web/protocol.go:200
return wireRegister{
Type: "register",
Platform: name,
Client: "cc-connect",
Project: project,
Transport: transport,
Metadata: map[string]any{
"protocol_version": protocolVersion,
},
}
}
func parseRegisterAck(raw []byte) (map[string]bool, error) {
var ack wireRegisterAck
if err := json.Unmarshal(raw, &ack); err != nil {
return nil, fmt.Errorf("cloud_web: parse register_ack: %w", err)
}
if ack.Type != "register_ack" {
return nil, fmt.Errorf("cloud_web: expected register_ack, got %q", ack.Type)
}
if !ack.OK {
if ack.Error != "" {
return nil, fmt.Errorf("cloud_web: register rejected: %s", ack.Error)
}
return nil, fmt.Errorf("cloud_web: register rejected")
}
if len(ack.Capabilities) == 0 {
return defaultCapabilities(), nil
}
return capabilitySet(ack.Capabilities), nil
}
func decodeImages(items []wireImage) []core.ImageAttachment {
var out []core.ImageAttachment
for _, img := range items {
data, err := base64.StdEncoding.DecodeString(img.Data)
if err != nil {View on GitHub (pinned to 4000b2338a)
Solutions
- Log the received frame's type to see what the server actually sent first
- Check client/server protocol versions are aligned; redeploy whichever side is out of date
- Ensure the cloud-web server is configured to reply with register_ack immediately after connection registration
- Verify the wsURL routes to the cloud-web hub, not another WebSocket service that speaks a different message type
Example fix
// before (debugging)
return nil, fmt.Errorf("cloud_web: expected register_ack, got %q", ack.Type)
// after (surface the payload to identify the frame)
return nil, fmt.Errorf("cloud_web: expected register_ack, got %q (raw=%s)", ack.Type, string(raw)) Defensive patterns
Strategy: retry
Try / catch
// Retry connectLoop; log the unexpected frame type first
if err := connect(ctx); err != nil {
var protoErr = "expected register_ack"
if strings.Contains(err.Error(), protoErr) {
slog.Warn("cloud-web sent unexpected first frame; retrying", "err", err)
time.Sleep(backoff)
continue
}
} Prevention
- Align client/server handshake versions before deploying either side
- Confirm the server sends register_ack as the very first frame
- Never share the wsURL/port with another WebSocket service
- Add the frame type to connection error logs
When it happens
Trigger: The first WebSocket message after connect is a JSON object whose "type" field is anything other than "register_ack" (e.g. "error", "welcome", "push", or empty), while it still parses as valid JSON.
Common situations: Server sends an error/welcome/heartbeat frame before the ack; server protocol updated its handshake ordering (version mismatch between client and server); a misconfigured endpoint routes to the wrong service that speaks a different message protocol on the same port.
Related errors
- cloud_web: parse register_ack: %w
- expected op 10 (Hello), got op %d
- expected READY event, got op=%d t=%s
- codex app-server initialize: %w
- cloud_web: ws_url or base_url is required for websocket tran
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/3438cbde6550eba8.
Report an issue: GitHub.