siyuan-note/siyuan · error
invalid custom emoji image
Error message
invalid custom emoji image
What it means
For raster images (png/jpeg/gif/webp), normalizeCustomEmojiData decodes the image configuration via image.DecodeConfig and enforces sane dimensions: width/height >= 1, <= 16384, and width*height <= 100M pixels. If decoding fails or the dimensions are out of bounds, it fails with 'invalid custom emoji image'.
Solutions
- Verify the file is a valid image and opens in an image viewer
- Re-export/resize the image to reasonable dimensions (under 16384x16384 and 100M pixels)
- Re-download — the file may be truncated or corrupted
- Ensure the URL serves raw image bytes, not a webpage
Defensive patterns
Strategy: validation
Validate before calling
const img = new Image();
img.onload = () => {
if (img.width < 1 || img.width > 16384 || img.height < 1 || img.height > 16384)
throw new Error("emoji dimensions out of range");
};
img.src = url; Try / catch
try {
await registerEmoji(data);
} catch (e) {
if (String(e).includes("invalid custom emoji image")) {
notifyUser("File is not a decodable image or its dimensions are too extreme");
}
} Prevention
- Open the image locally to confirm it decodes
- Keep dimensions under 16384x16384 and 100M pixels total
- Re-download truncated/corrupt files
- Never point emoji URLs at HTML pages
When it happens
Trigger: Downloading a file whose content is not a decodable raster image despite the extension (corrupted file, HTML error page), or an image with extreme dimensions (e.g. a 20000x20000 decompression-bomb PNG).
Common situations: URL serves an HTML login/error page with image extension; truncated download yields undecodable bytes; attacker-supplied huge-dimension image blocked as a decompression bomb.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Argon2id Iterations too low (minimum 3)
- asset path escapes data directory
- asset path escapes data directory
- custom emoji file must not be empty
- export path is outside export directory
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/3cf2ee986131688d.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/api/system.go:383
raster := true
switch http.DetectContentType(data) {
case "image/png":
ext = ".png"
case "image/jpeg":
ext = ".jpg"
case "image/gif":
ext = ".gif"
case "image/webp":
ext = ".webp"
default:
raster = false
}
if raster {
config, _, decodeErr := image.DecodeConfig(bytes.NewReader(data))
if decodeErr != nil || config.Width < 1 || config.Height < 1 || config.Width > 16384 || config.Height > 16384 ||
int64(config.Width)*int64(config.Height) > 100*1000*1000 {
return nil, "", fmt.Errorf("invalid custom emoji image")
}
return data, ext, nil
}
sanitizedSVG, sanitizeErr := util.SanitizeSVG(string(data))
if sanitizeErr == nil {
return []byte(sanitizedSVG), ".svg", nil
}
return nil, "", fmt.Errorf("unsupported custom emoji image format")
}
func normalizeCustomEmojiPath(name, ext string) (string, error) {
name = strings.TrimSpace(strings.ReplaceAll(name, "\\", "/"))
parts := strings.Split(name, "/")
if len(parts) == 0 {
return "", fmt.Errorf("custom emoji name must not be empty")
}
View on GitHub (pinned to 9f775e8a12)