{"record":{"id":"4ffca0b45346e08c","repo":"chenhg5/cc-connect","slug":"wecom-ws-file-data-is-empty","errorCode":null,"errorMessage":"wecom-ws: file data is empty","messagePattern":"wecom-ws: file data is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/websocket_outbound_media.go","lineNumber":168,"sourceCode":"\t\treturn \"image.gif\"\n\tcase \"image/webp\":\n\t\treturn \"image.webp\"\n\tdefault:\n\t\treturn \"image.png\"\n\t}\n}\n\n// SendFile uploads and sends a file through the WeCom AI Bot WebSocket API.\nfunc (p *WSPlatform) SendFile(ctx context.Context, rctx any, file core.FileAttachment) error {\n\trc, ok := rctx.(wsReplyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"wecom-ws: SendFile: invalid reply context type %T\", rctx)\n\t}\n\tif rc.chatID == \"\" {\n\t\treturn fmt.Errorf(\"wecom-ws: chatID is empty, cannot send file\")\n\t}\n\tif len(file.Data) == 0 {\n\t\treturn fmt.Errorf(\"wecom-ws: file data is empty\")\n\t}\n\n\tmediaID, err := p.uploadWSMedia(ctx, \"file\", wsFileFileName(file), file.Data)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"wecom-ws: send file: %w\", err)\n\t}\n\tif err := p.sendWSMediaMessage(ctx, rc.chatID, \"file\", mediaID); err != nil {\n\t\treturn fmt.Errorf(\"wecom-ws: send file: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc wsFileFileName(file core.FileAttachment) string {\n\tname := filepath.Base(strings.TrimSpace(file.FileName))\n\tif name != \"\" && name != \".\" {\n\t\treturn name\n\t}\n\tswitch strings.ToLower(file.MimeType) {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/websocket_outbound_media.go#L150-L186","documentation":"JSON parse failure on the response of POST /cgi-bin/message/send for an image message: the HTTP call itself succeeded but the body is not valid JSON matching the {errcode, errmsg} shape. Typically the endpoint returned an HTML error page (gateway/proxy issue), an auth redirect, or a truncated body instead of the expected API envelope.","triggerScenarios":"Called with core.FileAttachment{...} where Data is nil or an empty slice — e.g. a failed prior file read, or an attachment constructed with only FileName/Path but never loaded.","commonSituations":"Caller passed a path expecting the platform to read it (it does not — Data must be preloaded); the file was read with an error that was ignored; attachment produced from an empty download.","solutions":["Load the file bytes into file.Data before calling SendFile (e.g. os.ReadFile into Data)","Check len(file.Data) at the call site and skip/queue empty attachments","Verify the upstream read/download that populated Data actually succeeded"],"exampleFix":"// before\nfile := core.FileAttachment{FileName: \"report.pdf\"} // Data empty\np.SendFile(ctx, rc, file)\n// after\ndata, err := os.ReadFile(\"report.pdf\")\nif err != nil {\n\treturn err\n}\nfile := core.FileAttachment{FileName: \"report.pdf\", Data: data}\np.SendFile(ctx, rc, file)","handlingStrategy":"validation","validationCode":"if len(file.Data) == 0 {\n\treturn fmt.Errorf(\"attachment %s has no data; load bytes before SendFile\", file.FileName)\n}","typeGuard":null,"tryCatchPattern":"if err := p.SendFile(ctx, rc, file); err != nil && strings.Contains(err.Error(), \"file data is empty\") {\n\tlog.Warn(\"empty attachment skipped\", \"name\", file.FileName)\n}","preventionTips":["Read file bytes into Data at attachment-creation time; check the read error","Note SendFile does not read from disk — Data must be preloaded","Filter out zero-byte attachments before queueing"],"tags":["validation","empty-field","file-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"}