{"record":{"id":"d78ea029a659de09","repo":"chenhg5/cc-connect","slug":"wecom-ws-image-data-is-empty","errorCode":null,"errorMessage":"wecom-ws: image data is empty","messagePattern":"wecom-ws: image data is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/websocket_outbound_media.go","lineNumber":31,"sourceCode":"\t\"github.com/chenhg5/cc-connect/core\"\n)\n\nconst (\n\twecomWSUploadChunkSize = 512 * 1024\n\twecomWSUploadMaxChunks = 100\n)\n\n// SendImage uploads and sends an image through the WeCom AI Bot WebSocket API.\nfunc (p *WSPlatform) SendImage(ctx context.Context, rctx any, img core.ImageAttachment) error {\n\trc, ok := rctx.(wsReplyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"wecom-ws: SendImage: invalid reply context type %T\", rctx)\n\t}\n\tif rc.chatID == \"\" {\n\t\treturn fmt.Errorf(\"wecom-ws: chatID is empty, cannot send image\")\n\t}\n\tif len(img.Data) == 0 {\n\t\treturn fmt.Errorf(\"wecom-ws: image data is empty\")\n\t}\n\n\tmediaID, err := p.uploadWSMedia(ctx, \"image\", wsImageFileName(img), img.Data)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"wecom-ws: send image: %w\", err)\n\t}\n\tif err := p.sendWSMediaMessage(ctx, rc.chatID, \"image\", mediaID); err != nil {\n\t\treturn fmt.Errorf(\"wecom-ws: send image: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc (p *WSPlatform) uploadWSMedia(ctx context.Context, mediaType, filename string, data []byte) (string, error) {\n\ttotalChunks := (len(data) + wecomWSUploadChunkSize - 1) / wecomWSUploadChunkSize\n\tif totalChunks == 0 {\n\t\treturn \"\", fmt.Errorf(\"empty media data\")\n\t}\n\tif totalChunks > wecomWSUploadMaxChunks {","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/websocket_outbound_media.go#L13-L49","documentation":"SendImage rejects the call when core.ImageAttachment.Data is empty (len == 0) because there are no image bytes to chunk-upload to WeCom. This is a fail-fast validation before the chunked media upload, which would otherwise fail with a less obvious 'empty media data' error inside uploadWSMedia.","triggerScenarios":"Calling SendImage with an ImageAttachment whose Data slice is nil or zero-length: constructing the attachment without loading file contents, a failed/cancelled file read that returned no bytes but no error, or forwarding an attachment where only metadata (filename/mime) was set.","commonSituations":"os.ReadFile failing silently in caller code that ignores the error and passes a nil Data; agent adapters emitting attachment metadata without inline data; test fixtures that forgot to fill Data; files of zero bytes on disk.","solutions":["Verify img.Data is populated before calling SendImage: check the file read succeeded and len(img.Data) > 0.","Fix the upstream producer of the ImageAttachment (agent adapter or file loader) so it embeds actual bytes or returns an error.","Check that the source file on disk is non-empty and was read completely (no early EOF handling that returns nil data).","In tests, set Data to a small valid image payload (e.g. []byte of PNG bytes)."],"exampleFix":"// before\ndata, _ := os.ReadFile(path) // error ignored\ncore.ImageAttachment{FileName: \"x.png\"} // Data never set\n// after\ndata, err := os.ReadFile(path)\nif err != nil { return err }\ncore.ImageAttachment{FileName: \"x.png\", Data: data}","handlingStrategy":"validation","validationCode":"if len(img.Data) == 0 {\n    return errors.New(\"cannot send image: attachment has no data\")\n}","typeGuard":null,"tryCatchPattern":"if err := platform.SendImage(ctx, rctx, img); err != nil {\n    if strings.Contains(err.Error(), \"image data is empty\") {\n        // log and skip; investigate the attachment producer\n    }\n}","preventionTips":["Always check the error from file reads before building an ImageAttachment.","Validate attachments at the boundary: reject empty Data early in your pipeline.","Ensure agent adapters emit inline bytes, not just metadata, for image attachments.","Add a test fixture asserting Data is non-empty for every image send path."],"tags":["go","wecom","empty-value","media-upload"],"backgroundTag":"empty-required-field","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}