siyuan-note/siyuan · error
download custom emoji failed with status
Error message
download custom emoji failed with status %d
What it means
downloadCustomEmojiData fetches a custom emoji image over HTTP and requires a 200 OK response. Any other status code (404, 403, 500, redirects that end in error, etc.) aborts the download with this error. It protects callers from writing error pages or empty responses to disk as emoji files.
Solutions
- Verify the URL is reachable and returns 200 (curl -I the URL)
- Check whether the remote host requires auth or blocks hotlinking; use a URL that serves the raw image
- If behind a proxy, fix proxy/auth settings so the request succeeds
- Retry later if the status is 429 or 5xx from a transient upstream
Example fix
// before
resp := util.NewCustomReqClient().R().Get(url)
// after (check status before consuming)
if resp.StatusCode() != 200 {
return fmt.Errorf("emoji URL returned %d; use a direct image URL", resp.StatusCode())
} Defensive patterns
Strategy: validation
Validate before calling
const resp = await fetch(url, {method: "HEAD"});
if (!resp.ok) throw new Error(`emoji URL returned ${resp.status}; use a direct image URL`); Try / catch
try {
const data = await downloadEmoji(url);
} catch (e) {
if (String(e).includes("failed with status")) {
notifyUser("The emoji URL is unreachable or returned an error page; check the URL");
}
} Prevention
- Verify URLs return 200 with a HEAD request before registering
- Use direct raw-image URLs (e.g. raw.githubusercontent) not webpage links
- Avoid hosts with hotlink protection or aggressive rate limits
When it happens
Trigger: The URL passed to the custom emoji download API (readCustomEmojiData flow) resolves to a server that answers with a non-200 HTTP status: missing file on the remote host, expired/hotlink-protected CDN link, or a proxy returning 403/502.
Common situations: Emoji URL points to a deleted GitHub repo path or renamed branch; corporate proxy blocks the request; rate-limited CDN returns 429; user pasted a webpage URL instead of a direct image URL.
Related errors
- download custom emoji failed
- download failed:
- download failed: HTTP
- download failed
- download generated image failed with status
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/7f9697b0c2a85c42.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/api/system.go:348
if rawURL == "" {
return nil, fmt.Errorf("field [file] or [url] must not be empty")
}
return downloadCustomEmojiData(rawURL)
}
func downloadCustomEmojiData(rawURL string) ([]byte, error) {
parsedURL, err := url.Parse(rawURL)
if err != nil || (parsedURL.Scheme != "http" && parsedURL.Scheme != "https") || parsedURL.Host == "" {
return nil, fmt.Errorf("invalid custom emoji URL")
}
response, err := util.NewCustomReqClient().R().Get(parsedURL.String())
if err != nil {
return nil, fmt.Errorf("download custom emoji failed: %w", err)
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("download custom emoji failed with status %d", response.StatusCode)
}
if response.ContentLength > maxCustomEmojiSize {
return nil, fmt.Errorf("custom emoji file is too large")
}
data, err := io.ReadAll(io.LimitReader(response.Body, maxCustomEmojiSize+1))
if err != nil {
return nil, fmt.Errorf("read custom emoji response failed: %w", err)
}
return data, nil
}
func normalizeCustomEmojiData(data []byte) (normalized []byte, ext string, err error) {
if len(data) == 0 {
return nil, "", fmt.Errorf("custom emoji file must not be empty")
}
raster := trueView on GitHub (pinned to 9f775e8a12)