{"record":{"id":"7e801314ec595dac","repo":"chenhg5/cc-connect","slug":"dingtalk-upload-image-w","errorCode":null,"errorMessage":"dingtalk: upload image: %w","messagePattern":"dingtalk: upload image: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":1027,"sourceCode":"\t}\n}\n\n// SendImage uploads and sends an image via DingTalk oToMessages API.\n// Implements core.ImageSender.\nfunc (p *Platform) SendImage(ctx context.Context, rctx any, img core.ImageAttachment) error {\n\trc, ok := rctx.(replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"dingtalk: SendImage: invalid reply context type %T\", rctx)\n\t}\n\n\tname := img.FileName\n\tif name == \"\" {\n\t\tname = \"image.png\"\n\t}\n\n\tmediaID, err := p.uploadMedia(ctx, img.Data, name, \"image\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: upload image: %w\", err)\n\t}\n\n\tslog.Debug(\"dingtalk: image uploaded\", \"media_id\", mediaID, \"size\", len(img.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\tmsgParamBytes, _ := json.Marshal(map[string]string{\"photoURL\": mediaID})\n\trequestBody := map[string]any{\n\t\t\"robotCode\": p.robotCode,\n\t\t\"userIds\":   []string{rc.senderStaffId},\n\t\t\"msgKey\":    \"sampleImageMsg\",\n\t\t\"msgParam\":  string(msgParamBytes),\n\t}\n\n\tbody, err := json.Marshal(requestBody)","sourceCodeStart":1009,"sourceCodeEnd":1045,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L1009-L1045","documentation":"This error is returned by Platform.SendImage when p.uploadMedia fails — the step that uploads the image bytes to DingTalk's media API to obtain a mediaID before sending the oToMessages image message. The wrapped err contains the underlying cause: HTTP failure, non-2xx response from the media endpoint, invalid file, or authentication problems. Without a mediaID the image message cannot be constructed, so SendImage aborts.","triggerScenarios":"uploadMedia returns an error during SendImage — media endpoint unreachable, DingTalk rejects the upload (file too large, unsupported media type \"image\", invalid token), or the multipart upload itself fails.","commonSituations":"Image exceeds DingTalk's media size limit (e.g. very large screenshots pasted from chat); image data corrupted or empty; access token invalid at upload time; firewall blocking the media upload domain.","solutions":["Check the wrapped error for the actual upload failure (status code / errcode from the media API)","Verify the image size is within DingTalk's media upload limit (compress or downscale large images)","Confirm img.Data is non-empty and the file is a valid image with a supported extension","Check network access to DingTalk's media upload endpoint from the host","Retry — transient upload failures are common on flaky networks"],"exampleFix":"// before: sending a 25MB screenshot\nimg := core.ImageAttachment{Data: bigScreenshot, FileName: \"shot.png\"}\nerr := p.SendImage(ctx, rc, img)\n// after: downscale/compress before sending\nif len(img.Data) > dingTalkMediaMaxSize {\n    img.Data = compressImage(img.Data)\n}\nerr := p.SendImage(ctx, rc, img)","handlingStrategy":"validation","validationCode":"// Go: validate the image before uploading\nif len(img.Data) == 0 {\n    return errors.New(\"sendImage: empty image data\")\n}\nconst maxDingTalkMedia = 20 << 20 // 20MB\nif len(img.Data) > maxDingTalkMedia {\n    return fmt.Errorf(\"sendImage: image %d bytes exceeds limit\", len(img.Data))\n}","typeGuard":null,"tryCatchPattern":"if err := p.SendImage(ctx, rctx, img); err != nil {\n    if strings.Contains(err.Error(), \"upload image\") {\n        // check wrapped cause: size limit, bad media, or network\n        slog.Warn(\"dingtalk media upload failed, skipping image\",\n            \"err\", err, \"size\", len(img.Data))\n        return sendTextFallback(ctx, rctx, \"[image could not be delivered]\")\n    }\n    return err\n}","preventionTips":["Downscale/compress large screenshots before sending","Verify image bytes are non-empty and a supported format","Check media-domain egress from the host","Fall back to a text notice when upload fails so the user still gets a response"],"tags":["dingtalk","upload","image","http"],"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-14T00:17:10.932Z"}