{"record":{"id":"a3bb405397d79493","repo":"siyuan-note/siyuan","slug":"errinputtoolarge","errorCode":"ErrInputTooLarge","errorMessage":"HEIF image exceeds the input size limit","messagePattern":"HEIF image exceeds the input size limit","errorType":"error_code","errorClass":null,"httpStatus":413,"severity":"error","filePath":"kernel/heif/convert.go","lineNumber":52,"sourceCode":"const (\n\tthumbnailWidth   = 520\n\tpreviewQuality   = 90\n\tthumbnailQuality = 85\n\tMaxInputBytes    = 32 * 1024 * 1024\n\tmaxDimension     = 65535\n\tdesktopMaxPixels = 50_000_000\n\tmobileMaxPixels  = 12_500_000\n\t// 解码层仅接受至多 10-bit 4:2:0、无透明通道的单 slice 图像；这里按解码面、CTU 表、\n\t// NRGBA 和一次合并变换预留每像素 16 字节，再单独预留源文件、RBSP 副本与 JPEG 输出。\n\tworkingBytesPerPixel = 16\n\tdesktopWorkingBudget = 960 * 1024 * 1024\n\tmobileWorkingBudget  = 320 * 1024 * 1024\n\tdesktopOutputReserve = 96 * 1024 * 1024\n\tmobileOutputReserve  = 32 * 1024 * 1024\n)\n\nvar (\n\tErrInputTooLarge = errors.New(\"HEIF image exceeds the input size limit\")\n\tErrImageTooLarge = errors.New(\"HEIF image exceeds the dimension limit\")\n\tErrInvalidMode   = errors.New(\"invalid HEIF conversion mode\")\n\n\tconversionSlots = make(chan struct{}, 1)\n\tmaxPixels       = platformMaxPixels()\n)\n\nfunc platformMaxPixels() int {\n\tif runtime.GOOS == \"android\" || runtime.GOOS == \"ios\" {\n\t\treturn pixelsWithinBudget(mobileWorkingBudget, mobileOutputReserve, mobileMaxPixels)\n\t}\n\treturn pixelsWithinBudget(desktopWorkingBudget, desktopOutputReserve, desktopMaxPixels)\n}\n\nfunc ReadFileLimited(path string, maxBytes int64) ([]byte, error) {\n\tif maxBytes <= 0 {\n\t\treturn nil, ErrInputTooLarge\n\t}","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/heif/convert.go#L34-L70","documentation":"ErrInputTooLarge (kernel/heif/convert.go:52) is returned when a HEIF input exceeds MaxInputBytes = 32 MiB (convert.go:38). It is enforced at every entry point: convert (convert.go:105), ImageSize (158), ReadFileLimited (69/81 when reading the asset from disk), and cache GetOrCreate (cache.go:97). The cap bounds decoder memory; encrypted assets get a 2 MiB ciphertext margin when read (serve.go reads MaxInputBytes + 2 MiB).","triggerScenarios":"Inserting a .heic/.heif larger than 33554432 bytes; the preview pipeline (serve.go:1215/1255) reading such an asset; calling heif.ImageSize on oversized data (model/assets.go:69).","commonSituations":"High-megapixel phone HEIFs saved at near-lossless quality; panorama or burst exports; photos re-saved losslessly by editors pushing past 32 MiB.","solutions":["Re-export/compress the photo below 32 MiB (lower HEIF quality or reduce resolution)","Convert the image to JPEG before inserting - the original is still stored as a plain asset, only HEIF preview generation is refused","Prefer JPEG for very large captures, especially on mobile"],"exampleFix":"# before: insert photo_50mp_lossless.heic (40 MiB)\n# -> HEIF image exceeds the input size limit\n\n# after: re-encode below 32 MiB, then insert\nmagick photo_50mp_lossless.heic -quality 80 photo_small.heic","handlingStrategy":"validation","validationCode":"// Go: skip preview generation for oversized assets\nif fi, err := os.Stat(assetPath); err == nil && fi.Size() > int64(heif.MaxInputBytes) {\n    return nil // serve the original file as-is, skip HEIF preview\n}","typeGuard":"func isHEIFInputTooLarge(err error) bool {\n    return errors.Is(err, heif.ErrInputTooLarge)\n}","tryCatchPattern":null,"preventionTips":["Keep HEIF assets under 32 MiB (MaxInputBytes)","Pre-check size with os.Stat before calling heif APIs - the check is cheap and avoids a 32 MiB read","Transcode oversized captures to JPEG at import time"],"tags":["heif","image","size-limit","assets","resource-limits"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}