{"record":{"id":"20fb174ae51e8b5d","repo":"siyuan-note/siyuan","slug":"custom-emoji-file-is-too-large","errorCode":null,"errorMessage":"custom emoji file is too large","messagePattern":"custom emoji file is too large","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/system.go","lineNumber":343,"sourceCode":"\treturn downloadCustomEmojiData(rawURL)\n}\n\nfunc downloadCustomEmojiData(rawURL string) ([]byte, error) {\n\tparsedURL, err := url.Parse(rawURL)\n\tif err != nil || (parsedURL.Scheme != \"http\" && parsedURL.Scheme != \"https\") || parsedURL.Host == \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid custom emoji URL\")\n\t}\n\n\tresponse, err := util.NewCustomReqClient().R().Get(parsedURL.String())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"download custom emoji failed: %w\", err)\n\t}\n\tdefer response.Body.Close()\n\tif response.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"download custom emoji failed with status %d\", response.StatusCode)\n\t}\n\tif response.ContentLength > maxCustomEmojiSize {\n\t\treturn nil, fmt.Errorf(\"custom emoji file is too large\")\n\t}\n\n\tdata, err := io.ReadAll(io.LimitReader(response.Body, maxCustomEmojiSize+1))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read custom emoji response failed: %w\", err)\n\t}\n\treturn data, nil\n}\n\nfunc normalizeCustomEmojiData(data []byte) (normalized []byte, ext string, err error) {\n\tif len(data) == 0 {\n\t\treturn nil, \"\", fmt.Errorf(\"custom emoji file must not be empty\")\n\t}\n\n\traster := true\n\tswitch http.DetectContentType(data) {\n\tcase \"image/png\":\n\t\text = \".png\"","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/api/system.go#L325-L361","documentation":"Returned when the emoji payload exceeds maxCustomEmojiSize (10 MiB). Two throw sites: (1) downloadCustomEmojiData checks response.ContentLength > 10 MiB for the url path; (2) the addCustomEmoji handler checks len(data) > maxCustomEmojiSize for the uploaded file path. Note the url-path check only fires when the server advertises Content-Length; chunked responses with no length skip it and are instead capped by the LimitReader on line 348.","triggerScenarios":"Uploading an emoji file larger than 10 MiB via the file form field; or providing a url whose server reports Content-Length > 10 MiB. Animated GIFs, high-resolution PNGs, and oversized SVGs are the usual offenders.","commonSituations":"A full-resolution photo used as an emoji; a multi-megabyte animated GIF; a SVG exported with embedded base64 raster data inflating its size.","solutions":["Re-export the image at emoji-appropriate dimensions (e.g. 128x128 or 256x256) before uploading.","Strip metadata and re-compress: pngquant/oxipng for PNG, cwebp for WebP, gifsicle with --lossy for GIF.","If the emoji must be large, split it or accept the built-in 10 MiB cap cannot be raised without editing maxCustomEmojiSize and rebuilding.","For the url path, confirm the host sets Content-Length so the size guard actually fires; otherwise the LimitReader silently truncates at 10 MiB+1 and yields a corrupt-image error downstream."],"exampleFix":"// before\n// user uploads a 24 MiB photo as an emoji -> 413 too large\n\n// after: downscale and compress before upload\n//   convert icon.png -resize 128x128 icon_128.png\n//   oxipng -o3 icon_128.png   // typically < 100 KiB\n// then POST /api/system/addCustomEmoji with file=@icon_128.png","handlingStrategy":"validation","validationCode":"// Client-side: check size before upload\nconst MAX = 10 * 1024 * 1024\nfi, err := os.Stat(path)\nif err != nil { return err }\nif fi.Size() > MAX { return fmt.Errorf(\"file is %d bytes, max %d\", fi.Size(), MAX) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep emoji assets under 10 MiB; 256x256 png/webp is usually < 100 KiB.","For the url path, prefer hosts that report Content-Length so the server-side cap fires.","Strip EXIF/metadata before upload."],"tags":["validation","emoji","file-size","api"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}