sipeed/picoclaw · error
wecom upload requires 1-%d chunks, got %d
Error message
wecom upload requires 1-%d chunks, got %d
What it means
Defensive invariant in the WeCom chunked uploader: the file must produce between 1 and 100 chunks of 512KB (wecomUploadChunkMaxBytes = 512<<10, wecomUploadMaxChunks = 100). In practice this branch is unreachable, because outboundWeComMediaKind() already rejected files over 20MB (<= 40 chunks) and files under 5 bytes (which would yield 0 chunks) before the chunk math runs. Seeing it means the upstream kind-classification guard was bypassed or the constants were changed.
Source
Thrown at pkg/channels/wecom/media.go:692
) (*wecomOutboundMedia, error) {
_ = ctx
contentType = detectLocalWeComContentType(localPath, contentType)
filename = ensureWeComOutboundFilename(filename, localPath, contentType)
data, err := os.ReadFile(localPath)
if err != nil {
return nil, fmt.Errorf("read media file: %w", err)
}
size := int64(len(data))
kind := outboundWeComMediaKind(part.Type, filename, contentType, size)
if kind == "" {
return nil, fmt.Errorf("unsupported wecom media type or size for %q", filename)
}
totalChunks := (len(data) + wecomUploadChunkMaxBytes - 1) / wecomUploadChunkMaxBytes
if totalChunks <= 0 || totalChunks > wecomUploadMaxChunks {
return nil, fmt.Errorf("wecom upload requires 1-%d chunks, got %d", wecomUploadMaxChunks, totalChunks)
}
sum := md5.Sum(data)
initEnv, err := c.sendCommandAck(wecomCommand{
Cmd: wecomCmdUploadMediaInit,
Headers: wecomHeaders{ReqID: randomID(10)},
Body: wecomUploadMediaInitBody{
Type: kind,
Filename: filename,
TotalSize: size,
TotalChunks: totalChunks,
MD5: hex.EncodeToString(sum[:]),
},
}, wecomUploadTimeout)
if err != nil {
return nil, err
}
initResp, err := decodeWeComEnvelopeBody[wecomUploadMediaInitResponse](initEnv)View on GitHub (pinned to 49183d7e8d)
Solutions
- If you modified the size constants, scale wecomUploadMaxChunks accordingly (chunks = ceil(size/512KB)) or split the payload into multiple messages
- Otherwise treat this as a code-path bug: verify outboundWeComMediaKind ran before the chunk computation and file the invariant mismatch
- Reduce the attachment below the 20MB outbound cap so the normal classification path applies
Example fix
// before (constant drift) wecomOutboundMediaMaxBytes = 60 << 20 // raised, but chunks still capped at 100 -> error 661 // after wecomOutboundMediaMaxBytes = 60 << 20 wecomUploadMaxChunks = 128 // 60MB / 512KB = 120 chunks, give headroom
Defensive patterns
Strategy: validation
Validate before calling
// guard the invariant yourself if you tweak upload constants
const chunk = 512 << 10
func chunkCountOK(size int64) bool {
n := (size + chunk - 1) / chunk
return n >= 1 && n <= 100
}
if !chunkCountOK(info.Size()) { /* split or reject before send */ } Type guard
func isWecomChunkOverflow(err error) bool {
return err != nil && strings.Contains(err.Error(), "wecom upload requires 1-")
} Try / catch
if err := ch.Send(msg); err != nil {
if isWecomChunkOverflow(err) {
// configuration drift: re-check upload constants, then split the payload
}
} Prevention
- Never raise size caps without recomputing wecomUploadMaxChunks (ceil(maxBytes/512KB))
- Add a unit test asserting wecomUploadMaxChunks >= ceil(wecomOutboundMediaMaxBytes/chunk)
- Split very large payloads into multiple messages at the application layer
When it happens
Trigger: Only reachable if wecomOutboundMediaMaxBytes is raised above 100*512KB (~51.2MB) or the order of the kind check and chunk check is changed in uploadOutboundMedia; with current constants, len(data) is always 5..20,000,000, i.e. 1..40 chunks.
Common situations: A developer edits the upload limits in pkg/channels/wecom/media.go (e.g. raising the 20MB cap) without scaling wecomUploadMaxChunks; a fork adds a new media kind that skips the size guard; tests exercise the uploader with synthetic sizes past 50MB.
Related errors
- unsupported wecom media type or size for %q
- wecom upload init returned empty upload_id
- wecom upload finish returned empty media_id
- discord send media: %w
- feishu send media: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/2abd52ca8761467d.
Report an issue: GitHub.