{"record":{"id":"70021981d95e38ce","repo":"chenhg5/cc-connect","slug":"weixin-send-chunk-d-d-w","errorCode":null,"errorMessage":"weixin: send chunk %d/%d: %w","messagePattern":"weixin: send chunk (.+?)/(.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/weixin/weixin.go","lineNumber":852,"sourceCode":"\t\t\t}\n\t\t}\n\t\terr := p.sendChunk(ctx, rc, chunk)\n\t\tif err != nil {\n\t\t\tslog.Error(\"weixin: chunk send failed, message incomplete\",\n\t\t\t\t\"peer\", rc.peerUserID,\n\t\t\t\t\"failed_chunk\", fmt.Sprintf(\"%d/%d\", i+1, total),\n\t\t\t\t\"error\", err)\n\t\t\t// Notify user that message delivery was incomplete, unless the failure\n\t\t\t// is the ilink throttle: the notice send would be refused too, only\n\t\t\t// adding another throttled request.\n\t\t\tif !isSendThrottled(err) {\n\t\t\t\tnotice := \"⚠️ 消息发送不完整，请在终端查看完整结果。\"\n\t\t\t\tnoticeID := \"cc-\" + randomHex(6)\n\t\t\t\tif nerr := p.api.sendText(ctx, rc.peerUserID, notice, rc.contextToken, noticeID); nerr != nil {\n\t\t\t\t\tslog.Warn(\"weixin: failed to send incomplete-delivery notice\", \"peer\", rc.peerUserID, \"error\", nerr)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"weixin: send chunk %d/%d: %w\", i+1, total, err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// isSendThrottled reports whether err is ilink sendmessage's burst-throttle\n// response (ret=-2 \"prepare failed\"). This is a bot-wide rate-limit penalty, not a\n// context_token problem: the gateway accepts any (or no) context_token on sends.\nfunc isSendThrottled(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"ret=-2\")\n}\n\n// sendChunk sends a single chunk. If ilink throttles the send (ret=-2\n// \"prepare failed\"), it fails fast instead of retrying: live testing showed the\n// penalty is escalated by every send attempt made while it is active, so retrying\n// (e.g. the old 3×500ms loop plus the extra notice send) only prolongs the outage.\nfunc (p *Platform) sendChunk(ctx context.Context, rc *replyContext, chunk string) error {\n\tclientID := \"cc-\" + randomHex(6)","sourceCodeStart":834,"sourceCodeEnd":870,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/weixin/weixin.go#L834-L870","documentation":"sendChunks splits content into UTF-8-safe chunks and sends each via p.api.sendText. If any chunk fails after retries, the error is wrapped with its position (\"send chunk i/total\") so the caller knows the message was only partially delivered; an incomplete-delivery notice is attempted first.","triggerScenarios":"Any network/API failure while sending chunk i of total: HTTP error from ilink, timeout, invalid context_token rejected mid-sequence, or connection drop during a multi-chunk send.","commonSituations":"Long agent outputs spanning many chunks where a later chunk hits a network blip; expired context_token after the first chunks succeeded; ilink server errors under load; message larger than maxWeixinChunk combined with flaky connectivity.","solutions":["Inspect the wrapped inner error for the root cause (network vs API rejection)","Retry the whole send once connectivity is restored; duplicate chunks are usually idempotent via clientID","Shorten agent outputs or increase chunk budget to reduce partial-delivery exposure","Refresh the context_token (have the user message the bot) if rejections indicate token issues"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if len(content) == 0 {\n    return nil\n}\n// estimate chunk count to anticipate partial deliveries\nchunks := (len(content) + maxChunk - 1) / maxChunk","typeGuard":null,"tryCatchPattern":"if err := p.Send(ctx, rc, longMsg); err != nil {\n    var chunkErr string\n    if _, err2 := fmt.Sscanf(err.Error(), \"weixin: send chunk %d\", new(int)); err2 == nil || strings.Contains(err.Error(), \"send chunk\") {\n        log.Warn(\"partial delivery; retrying full message\", \"err\", err)\n        time.Sleep(backoff)\n        return p.Send(ctx, rc, longMsg)\n    }\n    _ = chunkErr\n    return err\n}","preventionTips":["Keep messages short to minimize chunk counts","Retry idempotently — clientIDs make duplicate sends detectable","Refresh context_token when later chunks get rejected","Monitor network stability of the host"],"tags":["go","network","weixin","partial-failure"],"backgroundTag":"http-request-failed","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"}