{"record":{"id":"dd3baf9bfd26da97","repo":"xpzouying/xiaohongshu-mcp","slug":"failed-to-create-request","errorCode":null,"errorMessage":"failed to create request","messagePattern":"failed to create request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/downloader/images.go","lineNumber":50,"sourceCode":"\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// 下载图片数据\n\tresp, err := d.httpClient.Do(req)\n\tif err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"failed to download image from %s\", imageURL)\n\t}\n\tdefer resp.Body.Close()\n","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/pkg/downloader/images.go#L32-L68","documentation":"DownloadImage wraps an http.NewRequest failure (pkg/downloader/images.go:50). Although isValidImageURL already rejects malformed URLs, http.NewRequest still parses the URL itself and can fail on control characters, invalid percent-escapes, or unsupported schemes that slipped past the prefix check. This is a client-side URL construction error — no network I/O has happened.","triggerScenarios":"Calling DownloadImage(url) or DownloadImages with a URL containing raw control characters (newline/tab from copied log lines), invalid percent-encoding like %zz, or a scheme http.NewRequest rejects, after passing the http(s)-prefix check.","commonSituations":"Image URLs scraped from HTML carrying embedded newlines or whitespace; unescaped characters from upstream data feeds; hand-built URLs with bad query encodings.","solutions":["Print/log the offending imageURL from the wrapped error and inspect for control characters or bad escapes.","Trim whitespace and re-encode: url.Parse + u.String(), or strings.TrimSpace before calling.","Validate with net/url.Parse yourself before invoking the downloader.","Sanitize at ingestion time so bad URLs never reach DownloadImages batches."],"exampleFix":"// before\npath, err := downloader.DownloadImage(rawURL)\n// after\ncleaned := strings.TrimSpace(rawURL)\nif _, err := url.Parse(cleaned); err != nil {\n    return fmt.Errorf(\"skip bad url %q: %w\", cleaned, err)\n}\npath, err := downloader.DownloadImage(cleaned)","handlingStrategy":"validation","validationCode":"u, err := url.Parse(strings.TrimSpace(rawURL))\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid image url %q\", rawURL)\n}","typeGuard":null,"tryCatchPattern":"path, err := dl.DownloadImage(imgURL)\nif err != nil && strings.Contains(err.Error(), \"failed to create request\") {\n    log.Printf(\"malformed url %q: %v\", imgURL, err)\n    return nil // skip bad URL in batch\n}","preventionTips":["Trim and re-encode scraped URLs (strip control chars/newlines).","Validate with url.Parse before downloading.","Sanitize URL sources at ingestion, not download time.","In batches, skip-and-log invalid URLs rather than aborting."],"tags":["http","url-validation","downloader","network"],"backgroundTag":"invalid-url","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"}