{"record":{"id":"ac16b88ab789ca4c","repo":"chenhg5/cc-connect","slug":"weixin-push-budget-exhausted-d-push-messages-in","errorCode":null,"errorMessage":"weixin: push budget exhausted (%d push messages in the last %s); ilink throttles the bot after roughly 5-6 pushes per window — reduce messages or re-login later","messagePattern":"weixin: push budget exhausted \\((.+?) push messages in the last (.+?)\\); ilink throttles the bot after roughly 5-6 pushes per window — reduce messages or re-login later","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/weixin/weixin.go","lineNumber":796,"sourceCode":"\tcutoff := now.Add(-p.sendQuotaWindow)\n\tkept := p.sendQuotaTimes[:0]\n\tfor _, t := range p.sendQuotaTimes {\n\t\tif t.After(cutoff) {\n\t\t\tkept = append(kept, t)\n\t\t}\n\t}\n\tp.sendQuotaTimes = kept\n\tif len(p.sendQuotaTimes) >= p.sendQuotaLimit {\n\t\tp.sendQuotaMu.Unlock()\n\t\tpushBudgetExceededCounter.Add(1)\n\t\tslog.Error(\"weixin: push_path_budget_exceeded\",\n\t\t\t\"path\", string(path),\n\t\t\t\"used\", len(p.sendQuotaTimes),\n\t\t\t\"limit\", p.sendQuotaLimit,\n\t\t\t\"window\", p.sendQuotaWindow.String(),\n\t\t\t\"hint\", \"ilink throttles the bot after roughly 5-6 pushes per window — reduce cron/timer pushes or re-login later\",\n\t\t)\n\t\treturn fmt.Errorf(\"weixin: push budget exhausted (%d push messages in the last %s); \"+\n\t\t\t\"ilink throttles the bot after roughly 5-6 pushes per window — reduce messages or re-login later\", p.sendQuotaLimit, p.sendQuotaWindow)\n\t}\n\tp.sendQuotaTimes = append(p.sendQuotaTimes, now)\n\tp.sendQuotaMu.Unlock()\n\treturn nil\n}\n\nfunc (p *Platform) sendChunks(ctx context.Context, replyCtx any, content string, path sendPath) error {\n\trc, ok := replyCtx.(*replyContext)\n\tif !ok || rc == nil {\n\t\treturn fmt.Errorf(\"weixin: invalid reply context\")\n\t}\n\tif err := p.checkSendQuota(ctx, path); err != nil {\n\t\treturn err\n\t}\n\tif strings.TrimSpace(rc.contextToken) == \"\" {\n\t\trc.contextToken = p.getContextToken(rc.peerUserID)\n\t}","sourceCodeStart":778,"sourceCodeEnd":814,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/weixin/weixin.go#L778-L814","documentation":"checkSendQuota enforces a sliding-window push budget because the ilink backend throttles the bot after roughly 5-6 pushed (non-reply) messages per window. When the number of recorded pushes within sendQuotaWindow reaches the limit, further pushes are rejected with this explanatory error.","triggerScenarios":"Send() (push path) is called more than sendQuotaLimit times within sendQuotaWindow, e.g. cron/timer jobs firing several messages back-to-back. Reply() bypasses this quota via sendPath.","commonSituations":"Multiple cron jobs or timers dispatching results simultaneously; a long agent output chunked into several pushes; burst of automated notifications after re-login; quota limits left at defaults while message volume grew.","solutions":["Reduce the number of pushed messages per window or batch content into one message","Increase sendQuotaLimit via configuration if acceptable for the account","Have the user message the bot and use Reply (replies bypass the push quota)","Wait until the sliding window expires and re-send"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// check quota pressure before pushing\ncount, window := p.PushQuotaUsage() // if exposed\nif count >= limit {\n    return fmt.Errorf(\"push budget %d/%d used in %s; defer send\", count, limit, window)\n}","typeGuard":null,"tryCatchPattern":"err := p.Send(ctx, rc, content)\nif err != nil && strings.Contains(err.Error(), \"push budget exhausted\") {\n    time.Sleep(window)\n    return p.Send(ctx, rc, content)\n}","preventionTips":["Batch multiple notifications into one message","Prefer Reply over proactive Send (replies bypass the quota)","Keep per-window pushes to ≤5","Schedule cron/timer output with jitter to avoid bursts"],"tags":["go","rate-limit","weixin","throttling"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}