chenhg5/cc-connect · error

weixin: send chunk %d/%d: %w

Error message

weixin: send chunk %d/%d: %w

What it means

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.

Source

Thrown at platform/weixin/weixin.go:852

			}
		}
		err := p.sendChunk(ctx, rc, chunk)
		if err != nil {
			slog.Error("weixin: chunk send failed, message incomplete",
				"peer", rc.peerUserID,
				"failed_chunk", fmt.Sprintf("%d/%d", i+1, total),
				"error", err)
			// Notify user that message delivery was incomplete, unless the failure
			// is the ilink throttle: the notice send would be refused too, only
			// adding another throttled request.
			if !isSendThrottled(err) {
				notice := "⚠️ 消息发送不完整,请在终端查看完整结果。"
				noticeID := "cc-" + randomHex(6)
				if nerr := p.api.sendText(ctx, rc.peerUserID, notice, rc.contextToken, noticeID); nerr != nil {
					slog.Warn("weixin: failed to send incomplete-delivery notice", "peer", rc.peerUserID, "error", nerr)
				}
			}
			return fmt.Errorf("weixin: send chunk %d/%d: %w", i+1, total, err)
		}
	}
	return nil
}

// isSendThrottled reports whether err is ilink sendmessage's burst-throttle
// response (ret=-2 "prepare failed"). This is a bot-wide rate-limit penalty, not a
// context_token problem: the gateway accepts any (or no) context_token on sends.
func isSendThrottled(err error) bool {
	return err != nil && strings.Contains(err.Error(), "ret=-2")
}

// sendChunk sends a single chunk. If ilink throttles the send (ret=-2
// "prepare failed"), it fails fast instead of retrying: live testing showed the
// penalty is escalated by every send attempt made while it is active, so retrying
// (e.g. the old 3×500ms loop plus the extra notice send) only prolongs the outage.
func (p *Platform) sendChunk(ctx context.Context, rc *replyContext, chunk string) error {
	clientID := "cc-" + randomHex(6)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the wrapped inner error for the root cause (network vs API rejection)
  2. Retry the whole send once connectivity is restored; duplicate chunks are usually idempotent via clientID
  3. Shorten agent outputs or increase chunk budget to reduce partial-delivery exposure
  4. Refresh the context_token (have the user message the bot) if rejections indicate token issues
Defensive patterns

Strategy: retry

Validate before calling

if len(content) == 0 {
    return nil
}
// estimate chunk count to anticipate partial deliveries
chunks := (len(content) + maxChunk - 1) / maxChunk

Try / catch

if err := p.Send(ctx, rc, longMsg); err != nil {
    var chunkErr string
    if _, err2 := fmt.Sscanf(err.Error(), "weixin: send chunk %d", new(int)); err2 == nil || strings.Contains(err.Error(), "send chunk") {
        log.Warn("partial delivery; retrying full message", "err", err)
        time.Sleep(backoff)
        return p.Send(ctx, rc, longMsg)
    }
    _ = chunkErr
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/70021981d95e38ce. Report an issue: GitHub.