{"record":{"id":"71d0dd7b0584b2c1","repo":"xpzouying/xiaohongshu-mcp","slug":"invalid-image-url-format","errorCode":null,"errorMessage":"invalid image URL format","messagePattern":"invalid image URL format","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/downloader/images.go","lineNumber":44,"sourceCode":"\t// 确保保存目录存在\n\tif err := os.MkdirAll(savePath, 0755); err != nil {\n\t\tpanic(fmt.Sprintf(\"failed to create save path: %v\", err))\n\t}\n\n\treturn &ImageDownloader{\n\t\tsavePath: savePath,\n\t\thttpClient: &http.Client{\n\t\t\tTimeout: 30 * time.Second,\n\t\t},\n\t}\n}\n\n// DownloadImage 下载图片\n// 返回本地文件路径\nfunc (d *ImageDownloader) DownloadImage(imageURL string) (string, error) {\n\t// 验证URL格式\n\tif !d.isValidImageURL(imageURL) {\n\t\treturn \"\", errors.New(\"invalid image URL format\")\n\t}\n\n\t// 创建请求并设置请求头\n\treq, err := http.NewRequest(\"GET\", imageURL, nil)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to create request\")\n\t}\n\n\t// 设置 User-Agent，模拟浏览器请求\n\treq.Header.Set(\"User-Agent\", \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\")\n\n\t// 设置 Referer，使用图片 URL 的域名\n\tparsedURL, _ := url.Parse(imageURL)\n\tif parsedURL != nil {\n\t\treq.Header.Set(\"Referer\", fmt.Sprintf(\"%s://%s/\", parsedURL.Scheme, parsedURL.Host))\n\t}\n\n\t// 下载图片数据","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/pkg/downloader/images.go#L26-L62","documentation":"DownloadImage validates the input URL with isValidImageURL before issuing the HTTP GET; if the URL fails that check it returns 'invalid image URL format' with an empty path. This is a fail-fast guard so the downloader never sends requests to malformed or non-image-looking URLs.","triggerScenarios":"Calling ImageDownloader.DownloadImage (pkg/downloader/images.go:44) with an empty string, a URL missing http/https scheme, a non-image extension, or garbage text that came from bad extraction of the image src attribute.","commonSituations":"Scraper captured a lazy-load placeholder or data URI instead of the real URL; note detail extraction returned relative paths without the CDN host; config file contains a mistyped image host; upstream API changed image URL shape.","solutions":["Print the offending URL and fix the extraction so full https CDN URLs are captured (prepend https://xcx.xiaohongshu.com for relative paths)","Pre-validate the URL in your pipeline before calling DownloadImage","Skip invalid URLs and continue the batch instead of aborting DownloadImages","If placeholder/1x1 URLs are the issue, wait for lazy-load images to hydrate before reading src"],"exampleFix":"// before\npath, err := downloader.DownloadImage(imgSrc)\nif err != nil { return err }\n// after\nif !strings.HasPrefix(imgSrc, \"http\") {\n    imgSrc = \"https://xcx.xiaohongshu.com\" + imgSrc\n}\npath, err := downloader.DownloadImage(imgSrc)\nif err != nil { log.Printf(\"skip image %q: %v\", imgSrc, err); continue }","handlingStrategy":"validation","validationCode":"func validImageURL(u string) bool {\n    p, err := url.Parse(u)\n    return err == nil && (p.Scheme == \"http\" || p.Scheme == \"https\") && p.Host != \"\"\n}\nif !validImageURL(imgSrc) { /* skip */ }","typeGuard":"func isDownloadableImageURL(s string) bool {\n    u, err := url.Parse(s)\n    return err == nil && u.IsAbs() && u.Host != \"\"\n}","tryCatchPattern":"path, err := downloader.DownloadImage(imgSrc)\nif err != nil && strings.Contains(err.Error(), \"invalid image URL format\") {\n    log.Printf(\"skipping bad URL %q\", imgSrc)\n    continue\n}","preventionTips":["Normalize relative image paths to absolute CDN URLs before download","Guard against lazy-load placeholders by waiting for image hydration","Validate URLs at extraction time, not download time"],"tags":["validation","download","url","images"],"backgroundTag":"invalid-url-format","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"}