{"record":{"id":"0087d22d2368d9fa","repo":"chenhg5/cc-connect","slug":"subscribe-response-w","errorCode":null,"errorMessage":"subscribe response: %w","messagePattern":"subscribe response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/websocket.go","lineNumber":244,"sourceCode":"\t// Send subscribe (auth) frame\n\t// Format: { cmd: \"aibot_subscribe\", headers: { req_id }, body: { bot_id, secret } }\n\tsubReqID := p.generateReqID(\"aibot_subscribe\")\n\tsubFrame := map[string]any{\n\t\t\"cmd\":     \"aibot_subscribe\",\n\t\t\"headers\": map[string]string{\"req_id\": subReqID},\n\t\t\"body\": map[string]string{\n\t\t\t\"bot_id\": p.botID,\n\t\t\t\"secret\": p.secret,\n\t\t},\n\t}\n\tif err := p.writeJSON(subFrame); err != nil {\n\t\treturn fmt.Errorf(\"subscribe: %w\", err)\n\t}\n\n\t// Read subscribe response: { headers: { req_id }, errcode: 0, errmsg: \"ok\" }\n\tvar subResp wsFrame\n\tif err := conn.ReadJSON(&subResp); err != nil {\n\t\treturn fmt.Errorf(\"subscribe response: %w\", err)\n\t}\n\tif subResp.ErrCode == nil || *subResp.ErrCode != 0 {\n\t\terrCode := 0\n\t\tif subResp.ErrCode != nil {\n\t\t\terrCode = *subResp.ErrCode\n\t\t}\n\t\treturn fmt.Errorf(\"subscribe failed: errcode=%d errmsg=%s\", errCode, subResp.ErrMsg)\n\t}\n\tslog.Info(\"wecom-ws: subscribed successfully\", \"bot_id\", p.botID)\n\tp.missedPong.Store(0)\n\n\t// Start heartbeat goroutine\n\theartCtx, heartCancel := context.WithCancel(p.ctx)\n\tdefer heartCancel()\n\tgo p.heartbeat(heartCtx, conn)\n\n\t// Read loop\n\tfor {","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/websocket.go#L226-L262","documentation":"After sending the subscribe frame, runConnection reads the subscribe response; this error wraps a ReadJSON failure while waiting for that ack. It means the socket failed or closed before a valid subscribe response frame arrived.","triggerScenarios":"The server closes the connection (invalid credentials, immediate reject), a read timeout/network drop occurs, or the context is canceled while blocked in ReadJSON.","commonSituations":"Wrong bot_id/bot_secret causing the server to disconnect instead of acking; WeCom endpoint closing idle or unauthenticated sockets quickly; network middleboxes killing the connection during handshake.","solutions":["Verify bot_id and bot_secret are correct — servers often close instead of returning an auth error frame.","Check the wrapped read error: 'unexpected EOF' / 'connection reset' suggests server-side close; 'use of closed connection' suggests local shutdown.","Confirm network stability and that no proxy is terminating websocket connections.","Let connectLoop retry; escalate if subscribe never succeeds across retries."],"exampleFix":"null","handlingStrategy":"retry","validationCode":"resp := authProbe(botID, secret) // test credentials against a lightweight WeCom token API before starting ws mode\nif resp.failed { return errors.New(\"invalid wecom credentials\") }","typeGuard":"null","tryCatchPattern":"err := platform.Start(ctx)\nif err != nil && strings.Contains(err.Error(), \"subscribe response\") {\n\t// likely server-side close: re-validate credentials, then retry\n\tvalidateCredentials(); retryWithBackoff(err)\n}","preventionTips":["Validate bot_id/bot_secret against the token API before ws connect","Watch for servers that close instead of acking bad credentials","Avoid proxies that terminate websocket handshakes mid-stream"],"tags":["wecom","websocket","subscribe","read"],"backgroundTag":"websocket-connection-closed","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"}