{"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":351,"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":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/api/system.go#L333-L369","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use a smaller/optimized image (resize or recompress before hosting)","Confirm the URL points to the actual emoji-sized image, not a large archive or page","Increase the emoji size budget if the deployment genuinely needs larger files","Strip query parameters pointing at oversized variants"],"exampleFix":"// before\nimg, _ := imageFromURL(hugeEmojiURL) // may exceed limit\n// after\nresize locally:\nsmall := resizeToUnderLimit(img, maxCustomEmojiSize)\nhostAndReference(small)","handlingStrategy":"validation","validationCode":"const size = (await fetch(url, {method: \"HEAD\"})).headers.get(\"content-length\");\nif (size && Number(size) > maxCustomEmojiSize) throw new Error(\"emoji too large; resize before use\");","typeGuard":null,"tryCatchPattern":"try {\n  await downloadEmoji(url);\n} catch (e) {\n  if (String(e).includes(\"too large\")) {\n    notifyUser(\"Compress or resize the image before using it as an emoji\");\n  }\n}","preventionTips":["Check Content-Length before downloading","Resize large images to emoji-appropriate dimensions (e.g. under 512px)","Point URLs at optimized variants, not originals"],"tags":["http","size-limit","download"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}