chenhg5/cc-connect · error
upload chunk %d: %w
Error message
upload chunk %d: %w
What it means
uploadWSMedia sends the file data to WeCom's AI Bot WebSocket API in base64-encoded chunks via 'aibot_upload_media_chunk' frames and waits for an ack for each chunk. This error wraps the failure of one of those per-chunk write/ack round trips (timeout, disconnected socket, or protocol error). The wrapped error identifies the underlying cause; the %d tells which chunk index failed.
Source
Thrown at platform/wecom/websocket_outbound_media.go:97
for i := 0; i < totalChunks; i++ {
start := i * wecomWSUploadChunkSize
end := start + wecomWSUploadChunkSize
if end > len(data) {
end = len(data)
}
reqID := p.generateReqID("aibot_upload_media_chunk")
chunkFrame := map[string]any{
"cmd": "aibot_upload_media_chunk",
"headers": map[string]string{"req_id": reqID},
"body": map[string]any{
"upload_id": initBody.UploadID,
"chunk_index": i,
"base64_data": base64.StdEncoding.EncodeToString(data[start:end]),
},
}
if _, err := p.writeAndWaitFrameWithTimeout(ctx, chunkFrame, reqID, wsMediaAckTimeout); err != nil {
return "", fmt.Errorf("upload chunk %d: %w", i, err)
}
}
finishReqID := p.generateReqID("aibot_upload_media_finish")
finishFrame := map[string]any{
"cmd": "aibot_upload_media_finish",
"headers": map[string]string{"req_id": finishReqID},
"body": map[string]any{
"upload_id": initBody.UploadID,
},
}
finishResp, err := p.writeAndWaitFrameWithTimeout(ctx, finishFrame, finishReqID, wsMediaAckTimeout)
if err != nil {
return "", fmt.Errorf("upload finish: %w", err)
}
var finishBody struct {
MediaID string `json:"media_id"`
}View on GitHub (pinned to 4000b2338a)
Solutions
- Check the wrapped cause: if it is a timeout, increase wsMediaAckTimeout or reduce chunk size for slow links
- Verify the WebSocket connection is alive before uploading (reconnect if needed) and retry the whole upload
- Confirm the WeCom AI Bot session/credentials are still valid — an expired session often fails mid-upload
- Log reqID and chunk index to correlate with WeCom server-side logs
Example fix
// before
if _, err := p.writeAndWaitFrameWithTimeout(ctx, chunkFrame, reqID, wsMediaAckTimeout); err != nil {
return "", fmt.Errorf("upload chunk %d: %w", i, err)
}
// after
if _, err := p.writeAndWaitFrameWithTimeout(ctx, chunkFrame, reqID, wsMediaAckTimeout); err != nil {
if p.conn == nil { // stale connection: reconnect once, then retry chunk
if rerr := p.reconnect(ctx); rerr != nil {
return "", fmt.Errorf("upload chunk %d: reconnect: %w", i, rerr)
}
return p.uploadWSMedia(ctx, mediaType, fileName, data)
}
return "", fmt.Errorf("upload chunk %d: %w", i, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if len(file.Data) == 0 || !p.IsConnected() {
return fmt.Errorf("wecom-ws: not connected or empty data, skipping upload")
} Try / catch
if err := p.SendFile(ctx, rc, file); err != nil {
var uerr *uploadChunkError
if errors.As(err, &uerr) && isTimeout(uerr.Unwrap()) {
// reconnect and retry once
}
log.Warn("wecom file upload failed", "err", err)
} Prevention
- Verify WS connectivity before starting uploads
- Keep chunk sizes modest so each ack lands well within wsMediaAckTimeout
- Retry full uploads idempotently with fresh upload_id
- Monitor WS reconnect frequency as an early warning
When it happens
Trigger: Called from SendImage or SendFile via uploadWSMedia when writeAndWaitFrameWithTimeout for chunk frame i returns an error: WS connection closed, ack not received within wsMediaAckTimeout, or the frame write failed.
Common situations: WebSocket dropped mid-upload (network blip, WeCom server restart); large files whose upload takes longer than the per-chunk ack timeout; token/session expiry invalidating the WS session; concurrent requests over the same WS connection desyncing request IDs.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/b358009c65bf2059.
Report an issue: GitHub.