xpzouying/xiaohongshu-mcp · error
failed to read image data
Error message
failed to read image data
What it means
DownloadImage wraps an io.ReadAll failure on the response body (pkg/downloader/images.go:76). The HTTP response already returned 200, but reading the streamed body failed — typically the connection was closed or reset mid-transfer, or a read deadline elapsed. The partial data is discarded; nothing is saved.
Source
Thrown at pkg/downloader/images.go:76
if parsedURL != nil {
req.Header.Set("Referer", fmt.Sprintf("%s://%s/", parsedURL.Scheme, parsedURL.Host))
}
// 下载图片数据
resp, err := d.httpClient.Do(req)
if err != nil {
return "", errors.Wrapf(err, "failed to download image from %s", imageURL)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("download failed with status %d for URL: %s", resp.StatusCode, imageURL)
}
// 读取图片数据
imageData, err := io.ReadAll(resp.Body)
if err != nil {
return "", errors.Wrap(err, "failed to read image data")
}
// 检测图片格式
kind, err := filetype.Match(imageData)
if err != nil {
return "", errors.Wrap(err, "failed to detect file type")
}
if !filetype.IsImage(imageData) {
return "", errors.New("downloaded file is not a valid image")
}
// 生成唯一文件名
fileName := d.generateFileName(imageURL, kind.Extension)
filePath := filepath.Join(d.savePath, fileName)
// 如果文件已存在,直接返回路径
if _, err := os.Stat(filePath); err == nil {View on GitHub (pinned to 332d196854)
Solutions
- Retry the download — transient connection resets usually succeed on a second attempt.
- If large files repeatedly truncate, the 30s client timeout may indirectly cut reads; increase NewImageDownloader's client timeout or stream to disk instead of io.ReadAll.
- Check for proxy interference and disable/reconfigure it.
- Add per-image retry with backoff in the calling loop (DownloadImages continues on error, so failed URLs are listed in its aggregate error).
Example fix
// before
for _, u := range urls {
p, err := dl.DownloadImage(u)
...
}
// after
for _, u := range urls {
var p string
err := retry.Do(3, func() error {
pp, e := dl.DownloadImage(u)
p = pp
return e
})
...
} Defensive patterns
Strategy: retry
Try / catch
path, err := dl.DownloadImage(imgURL)
if err != nil && strings.Contains(err.Error(), "failed to read image data") {
// body stream cut mid-transfer — retry once or twice
return retryWithBackoff(imgURL)
} Prevention
- Retry aborted body reads — resets are usually transient.
- Increase the http.Client timeout for large images or slow links.
- Avoid unstable proxies/keep-alive reuse for big transfers.
- Aggregate per-URL failures from DownloadImages and retry only those.
When it happens
Trigger: Calling DownloadImage when the server closes the connection mid-body, a proxy/load balancer cuts the stream, or the http.Client's transport hits an I/O error (e.g. 'unexpected EOF', 'connection reset by peer') while draining resp.Body.
Common situations: Large images over flaky mobile/proxy networks; CDN edge nodes aborting slow downloads; keep-alive connections reused after an idle drop; aggressive server-side timeouts.
Related errors
- failed to download image from %s
- download errors occurred: %v
- 下载图片失败 %s: %w
- failed to create request
- 下载内置浏览器失败: %w 本项目只用内置浏览器,缺它不继续。请检查网络后重试; 离线环境可手动下载 %s,解压
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/e3d666400aa911ed.
Report an issue: GitHub.