siyuan-note/siyuan · error

custom emoji file is too large

Error message

custom emoji file is too large

What it means

After a successful HTTP 200, the download size is checked: if Content-Length exceeds maxCustomEmojiSize the download is rejected with 'custom emoji file is too large'. This caps memory use and prevents giant files from being stored as emoji.

Solutions

  1. Use a smaller/optimized image (resize or recompress before hosting)
  2. Confirm the URL points to the actual emoji-sized image, not a large archive or page
  3. Increase the emoji size budget if the deployment genuinely needs larger files
  4. Strip query parameters pointing at oversized variants

Example fix

// before
img, _ := imageFromURL(hugeEmojiURL) // may exceed limit
// after
resize locally:
small := resizeToUnderLimit(img, maxCustomEmojiSize)
hostAndReference(small)
Defensive patterns

Strategy: validation

Validate before calling

const size = (await fetch(url, {method: "HEAD"})).headers.get("content-length");
if (size && Number(size) > maxCustomEmojiSize) throw new Error("emoji too large; resize before use");

Try / catch

try {
  await downloadEmoji(url);
} catch (e) {
  if (String(e).includes("too large")) {
    notifyUser("Compress or resize the image before using it as an emoji");
  }
}

Prevention

When it happens

Trigger: Downloading an emoji whose remote file size (response.ContentLength) exceeds maxCustomEmojiSize, e.g. a multi-MB image or a non-image URL that returns a large payload with 200.

Common situations: User pastes a URL to a huge PNG/PSD; a misconfigured server streams a whole archive with 200; trying to use an asset URL meant for other purposes.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/20fb174ae51e8b5d. Report an issue: GitHub.

Appendix: source

Thrown at kernel/api/system.go:351

	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 := true
	switch http.DetectContentType(data) {
	case "image/png":
		ext = ".png"

View on GitHub (pinned to 9f775e8a12)