{"record":{"id":"6cfde311172e6ecf","repo":"xpzouying/xiaohongshu-mcp","slug":"s-w","errorCode":null,"errorMessage":"下载图片失败 %s: %w","messagePattern":"下载图片失败 (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/downloader/processor.go","lineNumber":35,"sourceCode":"\t\tdownloader: NewImageDownloader(configs.GetImagesPath()),\n\t}\n}\n\n// ProcessImages 处理图片列表，返回本地文件路径\n// 支持两种输入格式：\n// 1. URL格式 (http/https开头) - 自动下载到本地\n// 2. 本地文件路径 - 直接使用\n// 保持原始图片顺序，如果下载失败直接返回错误\nfunc (p *ImageProcessor) ProcessImages(images []string) ([]string, error) {\n\tlocalPaths := make([]string, 0, len(images))\n\n\t// 按顺序处理每张图片\n\tfor _, image := range images {\n\t\tif IsImageURL(image) {\n\t\t\t// URL图片：立即下载，失败直接返回错误\n\t\t\tlocalPath, err := p.downloader.DownloadImage(image)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"下载图片失败 %s: %w\", image, err)\n\t\t\t}\n\t\t\tlocalPaths = append(localPaths, localPath)\n\t\t} else {\n\t\t\t// 本地路径直接使用\n\t\t\tlocalPaths = append(localPaths, image)\n\t\t}\n\t}\n\n\tif len(localPaths) == 0 {\n\t\treturn nil, fmt.Errorf(\"no valid images found\")\n\t}\n\n\treturn localPaths, nil\n}\n","sourceCodeStart":17,"sourceCodeEnd":50,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/pkg/downloader/processor.go#L17-L50","documentation":"ProcessImages processes an image list in order; for each URL-shaped image it downloads immediately via DownloadImage, and any download error aborts the whole batch with this wrapped error identifying the failing URL. Unlike DownloadImages (aggregate), this is fail-fast on the first bad image.","triggerScenarios":"Calling ProcessImages where an entry passes IsImageURL but DownloadImage fails — unreachable host, HTTP error, timeout, or invalid image content.","commonSituations":"Publishing Xiaohongshu content whose Markdown contains remote images hosted on dead or hotlink-protected CDNs; typos in image URLs; machine without internet access.","solutions":["Check the wrapped error and the %s URL for reachability (curl -I) and fix or remove the bad URL","Pre-validate all URLs with IsImageURL and an HTTP HEAD check before calling ProcessImages","Switch the failing image to a local file path (non-URL entries bypass downloading)","Add retry logic around ProcessImages for transient network errors"],"exampleFix":"// before\nlocalPaths, err := processor.ProcessImages(ctx, images)\n// after\nfor _, img := range images {\n    if IsImageURL(img) && !reachable(img) { return fmt.Errorf(\"image unreachable: %s\", img) }\n}\nlocalPaths, err := processor.ProcessImages(ctx, images)","handlingStrategy":"validation","validationCode":"for _, img := range images {\n    if IsImageURL(img) {\n        resp, err := http.Head(img)\n        if err != nil || resp.StatusCode >= 400 {\n            return fmt.Errorf(\"image url unreachable: %s\", img)\n        }\n    } else if _, err := os.Stat(img); err != nil {\n        return fmt.Errorf(\"local image missing: %s\", img)\n    }\n}","typeGuard":null,"tryCatchPattern":"localPaths, err := processor.ProcessImages(ctx, images)\nif err != nil {\n    if strings.Contains(err.Error(), \"下载图片失败\") {\n        return fmt.Errorf(\"pre-publish image download failed: %w\", err)\n    }\n    return err\n}","preventionTips":["Pre-validate every entry: URL shape + HTTP reachability, or os.Stat for local paths","Prefer hosting images on reliable storage rather than hotlinked third-party CDNs","Convert known-flaky URLs to local files before invoking ProcessImages","Add timeout/retry around the whole ProcessImages call for transient faults"],"tags":["go","downloader","network","fail-fast"],"backgroundTag":"image-download-failed","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}