{"record":{"id":"6baa24db8e69f586","repo":"chenhg5/cc-connect","slug":"wecom-ws-send-file-w","errorCode":null,"errorMessage":"wecom-ws: send file: %w","messagePattern":"wecom-ws: send file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/wecom/websocket_outbound_media.go","lineNumber":173,"sourceCode":"\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) {\n\tcase \"text/html\":\n\t\treturn \"file.html\"\n\tcase \"application/pdf\":\n\t\treturn \"file.pdf\"\n\tcase \"text/plain\":","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/wecom/websocket_outbound_media.go#L155-L191","documentation":"SendFile wraps any failure from uploadWSMedia (the init/chunk/finish WebSocket upload that yields a media_id) with this prefix. The wrapped error chain contains the real cause — upload chunk timeout, finish failure, or decode error from the same file.","triggerScenarios":"SendFile → uploadWSMedia returns any error: chunk send timeout, finish timeout, finish decode failure, or empty media_id.","commonSituations":"WS connection dropped during a large upload; per-chunk ack timeout on slow networks; WeCom server rejecting the upload session due to size or permissions.","solutions":["Unwrap the error chain (%w) to find the underlying upload stage that failed","Retry SendFile once after verifying the WS connection; transient timeouts are common","Reduce file size or chunk size if timeouts recur","Check WeCom AI Bot quota/permissions for media uploads"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if len(file.Data) == 0 || file.Data == nil {\n\treturn fmt.Errorf(\"no data to upload\")\n}","typeGuard":null,"tryCatchPattern":"if err := p.SendFile(ctx, rc, file); err != nil {\n\tvar netErr net.Error\n\tif errors.As(err, &netErr) && netErr.Timeout() {\n\t\t// reconnect WS and retry upload once\n\t}\n\treturn fmt.Errorf(\"file delivery failed: %w\", err)\n}","preventionTips":["Always inspect errors.As/Unwrap — the real cause is one level down","Check WS health before large uploads","Retry once for transient timeouts; abort on repeated failures"],"tags":["websocket","file-upload","error-wrapping"],"backgroundTag":"api-request-failed","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"}