{"record":{"id":"fbe9b20f35a190b5","repo":"xpzouying/xiaohongshu-mcp","slug":"failed-to-detect-file-type","errorCode":null,"errorMessage":"failed to detect file type","messagePattern":"failed to detect file type","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/downloader/images.go","lineNumber":82,"sourceCode":"\tif err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"failed to download image from %s\", imageURL)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"download failed with status %d for URL: %s\", resp.StatusCode, imageURL)\n\t}\n\n\t// 读取图片数据\n\timageData, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to read image data\")\n\t}\n\n\t// 检测图片格式\n\tkind, err := filetype.Match(imageData)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to detect file type\")\n\t}\n\n\tif !filetype.IsImage(imageData) {\n\t\treturn \"\", errors.New(\"downloaded file is not a valid image\")\n\t}\n\n\t// 生成唯一文件名\n\tfileName := d.generateFileName(imageURL, kind.Extension)\n\tfilePath := filepath.Join(d.savePath, fileName)\n\n\t// 如果文件已存在，直接返回路径\n\tif _, err := os.Stat(filePath); err == nil {\n\t\treturn filePath, nil\n\t}\n\n\t// 保存到文件\n\tif err := os.WriteFile(filePath, imageData, 0644); err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to save image\")","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/pkg/downloader/images.go#L64-L100","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nkind, err := filetype.Match(imageData)\nif err != nil {\n\treturn \"\", errors.Wrap(err, \"failed to detect file type\")\n}\n// after\nif len(imageData) == 0 {\n\treturn \"\", errors.New(\"empty image body (possibly blocked by CDN)\")\n}\nkind, err := filetype.Match(imageData)\nif err != nil {\n\treturn \"\", errors.Wrapf(err, \"failed to detect file type (first bytes: %x, content-type: %s)\", imageData[:min(8, len(imageData))], contentType)\n}","handlingStrategy":"validation","validationCode":"// 校验 URL 指向的内容确实是图片\nresp, err := http.Head(imageURL)\nif err != nil || resp.StatusCode != 200 {\n\treturn fmt.Errorf(\"URL unreachable: %v\", err)\n}\nif ct := resp.Header.Get(\"Content-Type\"); !strings.HasPrefix(ct, \"image/\") {\n\treturn fmt.Errorf(\"not an image content-type: %s\", ct)\n}","typeGuard":"func isLikelyImageData(b []byte) bool {\n\treturn len(b) > 16 && (bytes.HasPrefix(b, []byte{0xFF, 0xD8}) || // jpeg\n\t\tbytes.HasPrefix(b, []byte{0x89, 'P', 'N', 'G'}) || bytes.HasPrefix(b, []byte{'R', 'I', 'F', 'F'}))\n}","tryCatchPattern":"path, err := d.DownloadImage(url)\nif err != nil {\n\tif strings.Contains(err.Error(), \"failed to detect file type\") {\n\t\tlog.Printf(\"skipping %s: body is not a recognizable image (blocked or empty)\", url)\n\t\treturn \"\" // 跳过该图，不中断批量下载\n\t}\n\treturn \"\", err\n}","preventionTips":["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"],"tags":["go","http","image-download","filetype-detection"],"backgroundTag":"invalid-content-type-response","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"}