{"record":{"id":"3cf2ee986131688d","repo":"siyuan-note/siyuan","slug":"invalid-custom-emoji-image","errorCode":null,"errorMessage":"invalid custom emoji image","messagePattern":"invalid custom emoji image","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/system.go","lineNumber":375,"sourceCode":"\n\traster := true\n\tswitch http.DetectContentType(data) {\n\tcase \"image/png\":\n\t\text = \".png\"\n\tcase \"image/jpeg\":\n\t\text = \".jpg\"\n\tcase \"image/gif\":\n\t\text = \".gif\"\n\tcase \"image/webp\":\n\t\text = \".webp\"\n\tdefault:\n\t\traster = false\n\t}\n\tif raster {\n\t\tconfig, _, decodeErr := image.DecodeConfig(bytes.NewReader(data))\n\t\tif decodeErr != nil || config.Width < 1 || config.Height < 1 || config.Width > 16384 || config.Height > 16384 ||\n\t\t\tint64(config.Width)*int64(config.Height) > 100*1000*1000 {\n\t\t\treturn nil, \"\", fmt.Errorf(\"invalid custom emoji image\")\n\t\t}\n\t\treturn data, ext, nil\n\t}\n\n\tsanitizedSVG, sanitizeErr := util.SanitizeSVG(string(data))\n\tif sanitizeErr == nil {\n\t\treturn []byte(sanitizedSVG), \".svg\", nil\n\t}\n\treturn nil, \"\", fmt.Errorf(\"unsupported custom emoji image format\")\n}\n\nfunc normalizeCustomEmojiPath(name, ext string) (string, error) {\n\tname = strings.TrimSpace(strings.ReplaceAll(name, \"\\\\\", \"/\"))\n\tparts := strings.Split(name, \"/\")\n\tif len(parts) == 0 {\n\t\treturn \"\", fmt.Errorf(\"custom emoji name must not be empty\")\n\t}\n","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/api/system.go#L357-L393","documentation":"Returned by normalizeCustomEmojiData for raster images (png/jpeg/gif/webp detected by http.DetectContentType) when image.DecodeConfig fails OR the dimensions are invalid: width or height < 1, either side > 16384 px, or width*height > 100,000,000 pixels. The bytes smelled like a raster image but are corrupt or absurdly large.","triggerScenarios":"Uploading a truncated PNG/GIF (headers intact, body cut off so DecodeConfig fails), a deliberately huge dimension image (>16384 px), or a file with a spoofed extension whose magic bytes match a raster type but the body is malformed.","commonSituations":"Partial download saved as an image; a screenshot exported at extreme resolution; a file renamed .png but actually a different binary; a JPEG with only SOI marker.","solutions":["Re-open the file in an image editor and re-export to confirm it is a valid image.","Downscale so neither side exceeds 16384 px and total pixels stay under 100M.","Verify the file with `file icon.png` and `identify icon.png` (ImageMagick) before uploading.","If the file is valid but exotic (e.g. AVIF/HEIC), convert to png/webp first; those formats are not in the accepted set."],"exampleFix":"// before\n// uploading a truncated 20000x20000 png -> 'invalid custom emoji image'\n\n// after: validate locally first\n//   identify icon.png   # confirm dimensions are sane and body is complete\n//   convert icon.png -resize 512x512 icon_small.png\n// then upload icon_small.png","handlingStrategy":"validation","validationCode":"// Validate raster dimensions locally before uploading\ncfg, _, err := image.DecodeConfig(f)\nif err != nil { return fmt.Errorf(\"not a decodable image: %w\", err) }\nif cfg.Width < 1 || cfg.Height < 1 { return errors.New(\"invalid dimensions\") }\nif cfg.Width > 16384 || cfg.Height > 16384 { return errors.New(\"dimension exceeds 16384px\") }\nif int64(cfg.Width)*int64(cfg.Height) > 100_000_000 { return errors.New(\"pixel count exceeds 100M\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Re-export images through an editor to confirm body integrity.","Cap dimensions at 512-1024px for emoji use.","Verify with `identify`/`file` before uploading."],"tags":["validation","emoji","image-decode","api"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}