{"record":{"id":"403e36385cdfabee","repo":"chenhg5/cc-connect","slug":"cloud-web-parse-register-ack-w","errorCode":null,"errorMessage":"cloud_web: parse register_ack: %w","messagePattern":"cloud_web: parse register_ack: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/cloud-web/protocol.go","lineNumber":197,"sourceCode":"}\n\nfunc buildRegisterPayload(name, project, transport string) wireRegister {\n\treturn wireRegister{\n\t\tType:      \"register\",\n\t\tPlatform:  name,\n\t\tClient:    \"cc-connect\",\n\t\tProject:   project,\n\t\tTransport: transport,\n\t\tMetadata: map[string]any{\n\t\t\t\"protocol_version\": protocolVersion,\n\t\t},\n\t}\n}\n\nfunc parseRegisterAck(raw []byte) (map[string]bool, error) {\n\tvar ack wireRegisterAck\n\tif err := json.Unmarshal(raw, &ack); err != nil {\n\t\treturn nil, fmt.Errorf(\"cloud_web: parse register_ack: %w\", err)\n\t}\n\tif ack.Type != \"register_ack\" {\n\t\treturn nil, fmt.Errorf(\"cloud_web: expected register_ack, got %q\", ack.Type)\n\t}\n\tif !ack.OK {\n\t\tif ack.Error != \"\" {\n\t\t\treturn nil, fmt.Errorf(\"cloud_web: register rejected: %s\", ack.Error)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"cloud_web: register rejected\")\n\t}\n\tif len(ack.Capabilities) == 0 {\n\t\treturn defaultCapabilities(), nil\n\t}\n\treturn capabilitySet(ack.Capabilities), nil\n}\n\nfunc decodeImages(items []wireImage) []core.ImageAttachment {\n\tvar out []core.ImageAttachment","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/cloud-web/protocol.go#L179-L215","documentation":"parseRegisterAck wraps any JSON unmarshal failure of the server's register_ack frame with this prefixed error. The cloud-web transport requires every WebSocket connection to start with a valid register_ack JSON message; if the first frame is not decodable JSON into wireRegisterAck, the connection is closed and this error propagates to register/connectOnce. It means the remote cloud-web server sent malformed or unexpected bytes as its handshake acknowledgment.","triggerScenarios":"json.Unmarshal(raw, &ack) fails because the first WebSocket message after dial is not valid JSON, is an HTML error page from a reverse proxy, is binary, is empty (EOF), or is a valid JSON type other than the expected object shape.","commonSituations":"Connecting to an HTTP(S) URL instead of a ws(s):// URL so the proxy returns an HTML 4xx/5xx page; a load balancer or auth layer intercepting the upgrade and returning plain text; wrong port or path in config so a different service answers; server closes the connection immediately (empty frame); protocol version mismatch where the server sends a different handshake message first.","solutions":["Verify wsURL in config points at the cloud-web WebSocket endpoint (correct scheme, host, port, path), not an HTTP page or wrong service","Check what the server actually sends as its first frame (e.g. wscat or server logs); fix the server-side handshake or version mismatch","Confirm no reverse proxy/auth middleware is intercepting the WebSocket upgrade and returning HTML or plain text","Check network/proxy compression or TLS termination that could corrupt the frame; inspect the wrapped underlying error (%w) for the exact JSON failure"],"exampleFix":"// before (server not yet upgraded, sends old handshake)\ncaps, err := parseRegisterAck(raw)\n// after (log the raw frame to diagnose, then fix server/client version alignment)\nif err != nil {\n    slog.Error(\"cloud_web: bad register_ack\", \"raw\", string(raw), \"err\", err)\n}","handlingStrategy":"validation","validationCode":"// Validate the endpoint before dialing\nu, err := url.Parse(cfg.WSURL)\nif err != nil || u.Scheme != \"ws\" && u.Scheme != \"wss\" {\n    return fmt.Errorf(\"invalid cloud-web wsURL %q: %w\", cfg.WSURL, err)\n}","typeGuard":null,"tryCatchPattern":"// Treat wrapped json error as fatal config/protocol issue; log raw frame\nif err := register(ctx); err != nil {\n    if strings.Contains(err.Error(), \"parse register_ack\") {\n        slog.Error(\"cloud-web handshake returned non-JSON frame; check wsURL/proxy\", \"err\", err)\n        return err\n    }\n}","preventionTips":["Point wsURL at the real WebSocket endpoint, never an HTTP page","Keep client and server protocol versions in lockstep","Ensure proxies/LBs pass WebSocket upgrades through untouched","Log the first raw frame on handshake failure for fast diagnosis"],"tags":["websocket","json","handshake","cloud-web"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}