xpzouying/xiaohongshu-mcp · error
failed to detect file type
Error message
failed to detect file type
What it means
DownloadImage validates downloaded bytes with h2non/filetype before saving. filetype.Match fails when it cannot recognize the magic-number signature of the response body — i.e. the body is empty, truncated, or not a known binary file format. The library throws this so corrupt/HTML error pages never get written to disk with a guessed extension.
Source
Thrown at pkg/downloader/images.go:82
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 {
return filePath, nil
}
// 保存到文件
if err := os.WriteFile(filePath, imageData, 0644); err != nil {
return "", errors.Wrap(err, "failed to save image")View on GitHub (pinned to 332d196854)
Solutions
- Log the first bytes / resp.Content-Type of the body to see what was actually returned; if it is HTML, the CDN blocked the request — add valid cookies/UA/Referer or re-login
- Re-download the image; transient truncation often resolves on retry
- Check the h2non/filetype version and upgrade it if the source serves a newer format (e.g. AVIF)
- Verify the URL with curl -I / curl -o to confirm it actually returns image bytes before blaming the downloader
Example fix
// before
kind, err := filetype.Match(imageData)
if err != nil {
return "", errors.Wrap(err, "failed to detect file type")
}
// after
if len(imageData) == 0 {
return "", errors.New("empty image body (possibly blocked by CDN)")
}
kind, err := filetype.Match(imageData)
if err != nil {
return "", errors.Wrapf(err, "failed to detect file type (first bytes: %x, content-type: %s)", imageData[:min(8, len(imageData))], contentType)
} Defensive patterns
Strategy: validation
Validate before calling
// 校验 URL 指向的内容确实是图片
resp, err := http.Head(imageURL)
if err != nil || resp.StatusCode != 200 {
return fmt.Errorf("URL unreachable: %v", err)
}
if ct := resp.Header.Get("Content-Type"); !strings.HasPrefix(ct, "image/") {
return fmt.Errorf("not an image content-type: %s", ct)
} Type guard
func isLikelyImageData(b []byte) bool {
return len(b) > 16 && (bytes.HasPrefix(b, []byte{0xFF, 0xD8}) || // jpeg
bytes.HasPrefix(b, []byte{0x89, 'P', 'N', 'G'}) || bytes.HasPrefix(b, []byte{'R', 'I', 'F', 'F'}))
} Try / catch
path, err := d.DownloadImage(url)
if err != nil {
if strings.Contains(err.Error(), "failed to detect file type") {
log.Printf("skipping %s: body is not a recognizable image (blocked or empty)", url)
return "" // 跳过该图,不中断批量下载
}
return "", err
} Prevention
- Keep cookies/UA/Referer headers fresh so CDNs don't serve HTML block pages
- Log resp Content-Type and first bytes on failure to diagnose quickly
- Pin/upgrade github.com/h2non/filetype to support new image formats
- Retry transient downloads before giving up on truncation errors
When it happens
Trigger: Calling DownloadImage on a URL whose HTTP 200 body is not a real image: an empty body, an HTML anti-bot/login page served with 200, a zero-byte CDN placeholder, or a format filetype does not know (e.g. AVIF in old versions of the library).
Common situations: Xiaohongshu/CDN returns a captcha or 'verify' HTML page instead of the image; URL points at a redirect target that ends in an empty response; network truncates the transfer mid-body; remote server upgrades to a newer image format unsupported by the pinned filetype library version.
Related errors
- download failed with status %d for URL: %s
- 视频不能为空
- 获取 SHA256SUMS: HTTP %d
- HTTP %d: %s
- failed to download %s: %w
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/fbe9b20f35a190b5.
Report an issue: GitHub.