{"record":{"id":"39c84b3a893fa176","repo":"chenhg5/cc-connect","slug":"dingtalk-upload-file-w","errorCode":null,"errorMessage":"dingtalk: upload file: %w","messagePattern":"dingtalk: upload file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":1113,"sourceCode":"\treturn p.createAICard(ctx, rc)\n}\n\n// SendFile uploads and sends a file via DingTalk oToMessages API.\n// Implements core.FileSender.\nfunc (p *Platform) SendFile(ctx context.Context, rctx any, file core.FileAttachment) error {\n\trc, ok := rctx.(replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"dingtalk: SendFile: invalid reply context type %T\", rctx)\n\t}\n\n\tname := file.FileName\n\tif name == \"\" {\n\t\tname = \"file\"\n\t}\n\n\tmediaID, err := p.uploadMedia(ctx, file.Data, name, \"file\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: upload file: %w\", err)\n\t}\n\n\tslog.Debug(\"dingtalk: file uploaded\", \"media_id\", mediaID, \"name\", name, \"size\", len(file.Data))\n\n\ttoken, err := p.getAccessToken()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: get access token: %w\", err)\n\t}\n\n\text := \"\"\n\tif idx := strings.LastIndex(name, \".\"); idx >= 0 {\n\t\text = name[idx+1:]\n\t}\n\n\tmsgParamBytes, _ := json.Marshal(map[string]string{\n\t\t\"mediaId\":  mediaID,\n\t\t\"fileName\": name,\n\t\t\"fileType\": ext,","sourceCodeStart":1095,"sourceCodeEnd":1131,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L1095-L1131","documentation":"SendFile failed while uploading the file bytes to DingTalk's media upload API (uploadMedia), which returns the mediaID needed for the file message. The wrapped error carries the actual cause — upload HTTP failure, non-200 response, or token error.","triggerScenarios":"File too large for DingTalk media API limits; invalid mediaType; network failure during multipart upload; access token error inside uploadMedia; DingTalk rejecting the file name/content.","commonSituations":"Sending files > 20MB (DingTalk media limit); zero-byte or unreadable attachments; expired credentials; blocked network path to api.dingtalk.com.","solutions":["Read the wrapped error to identify the exact cause","Check the file size against DingTalk's media upload limit and compress/split if needed","Verify a valid access token is obtainable (check getAccessToken errors in logs)","Test connectivity to api.dingtalk.com from the host","Retry transient network failures with backoff"],"exampleFix":"// before\nfile.Data = hugeBuffer // 50MB\np.SendFile(ctx, rc, file)\n// after\nif len(file.Data) > 20*1024*1024 {\n    return fmt.Errorf(\"file exceeds DingTalk media limit\")\n}\np.SendFile(ctx, rc, file)","handlingStrategy":"validation","validationCode":"if len(file.Data) == 0 || len(file.Data) > 20*1024*1024 {\n    return fmt.Errorf(\"file size %d outside DingTalk media upload limits\", len(file.Data))\n}","typeGuard":null,"tryCatchPattern":"if err := p.SendFile(ctx, rc, file); err != nil {\n    if strings.Contains(err.Error(), \"upload file\") {\n        // uploadMedia failed; log wrapped cause and retry transient errors\n        slog.Error(\"media upload failed\", \"err\", err)\n    }\n    return err\n}","preventionTips":["Pre-check file size against DingTalk's media limits before upload","Ensure attachments are read fully and non-empty before sending","Retry transient upload failures with backoff","Keep access token credentials valid to avoid cascading failures"],"tags":["dingtalk","file-upload","media","http"],"backgroundTag":"http-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}