{"record":{"id":"5bfba99c15048682","repo":"chenhg5/cc-connect","slug":"subscribe-failed-errcode-d-errmsg-s","errorCode":null,"errorMessage":"subscribe failed: errcode=%d errmsg=%s","messagePattern":"subscribe failed: errcode=(.+?) errmsg=(.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/websocket.go","lineNumber":251,"sourceCode":"\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 {\n\t\tselect {\n\t\tcase <-p.ctx.Done():\n\t\t\treturn p.ctx.Err()\n\t\tdefault:\n\t\t}\n\n\t\t_, raw, err := conn.ReadMessage()","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/websocket.go#L233-L269","documentation":"The subscribe response arrived but carried a non-zero errcode, meaning the WeCom server explicitly rejected the subscription. The error includes the server's errcode and errmsg. Unlike read failures, this is an application-level rejection — the connection itself works.","triggerScenarios":"Server returns errcode != 0 in the subscribe response, typically due to invalid bot_id/bot_secret, bot disabled/deleted in the WeCom admin console, or IP not in the bot's allowlist.","commonSituations":"Rotated secret in config not updated; bot credentials from a different WeCom org; bot deactivated for inactivity; errcode indicating expired/invalid secret after a security policy change.","solutions":["Read errcode/errmsg in the error and map it via WeCom docs (usually auth/credential related).","Re-copy bot_id and bot_secret from the WeCom admin console into config.toml and restart.","Confirm the bot is enabled and its IP allowlist includes this host.","Regenerate the secret if it may have been revoked, then update config."],"exampleFix":"// before\nbot_secret = \"old-revoked-secret\"\n\n// after\nbot_secret = \"newly-regenerated-secret\"","handlingStrategy":"validation","validationCode":"tok := wecom.GetToken(botID, secret)\nif tok.ErrCode != 0 { return fmt.Errorf(\"invalid wecom credentials: errcode=%d\", tok.ErrCode) }","typeGuard":"null","tryCatchPattern":"err := platform.Start(ctx)\nvar subErr *SubscribeError\nif errors.As(err, &subErr) && isAuthCode(subErr.Code) {\n\trotateSecret(); restart()\n}","preventionTips":["Keep bot secrets in sync with the WeCom admin console","Set up alerts for bot deactivation/secret rotation","Ensure host IP is in the bot's allowlist","Pre-validate credentials with a token request at startup"],"tags":["wecom","websocket","authentication","subscribe"],"backgroundTag":"api-error-response","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"}