siyuan-note/siyuan · error
read custom emoji response failed
Error message
read custom emoji response failed: %w
What it means
Reading the HTTP response body into memory failed while downloading a custom emoji. The read is performed with io.ReadAll over a LimitReader capped at maxCustomEmojiSize+1, so only genuine I/O errors (connection reset, truncated body, timeouts) reach this wrapper.
Solutions
- Retry the download; transient truncation usually clears
- Check proxy/firewall stability for the remote host
- Use a more reliable mirror/CDN URL for the emoji
- Verify TLS/connectivity to the host (curl the URL to reproduce)
Example fix
// before
data, _ := io.ReadAll(body) // may fail mid-stream
// after
data, err := io.ReadAll(io.LimitReader(body, maxCustomEmojiSize+1))
if err != nil {
return retryDownload(url) // retry transient truncation
} Defensive patterns
Strategy: retry
Try / catch
try {
return await downloadEmoji(url);
} catch (e) {
if (String(e).includes("read custom emoji response failed")) {
return retryWithBackoff(() => downloadEmoji(url), 3); // transient truncation
}
throw e;
} Prevention
- Retry transient network failures with backoff
- Prefer stable CDN hosts over flaky origins
- Keep request timeouts generous enough for the file size
When it happens
Trigger: The connection drops or the server closes the stream mid-body during downloadCustomEmojiData; TLS interruption; read timeout while streaming the body.
Common situations: Flaky network or unstable proxy between the kernel and the emoji host; server aborts large responses; keep-alive reuse of a stale connection.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- read body failed:
- read body failed
- download custom emoji failed
- download custom emoji failed with status
- download failed:
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/98f2019529b7ae5a.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/api/system.go:356
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 := true
switch http.DetectContentType(data) {
case "image/png":
ext = ".png"
case "image/jpeg":
ext = ".jpg"
case "image/gif":
ext = ".gif"
case "image/webp":View on GitHub (pinned to 9f775e8a12)