{"record":{"id":"50b5e6d01afc7696","repo":"siyuan-note/siyuan","slug":"read-heif-image-dimensions-w","errorCode":null,"errorMessage":"read HEIF image dimensions: %w","messagePattern":"read HEIF image dimensions: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/heif/convert.go","lineNumber":186,"sourceCode":"\t}\n\twidth, height = img.Bounds().Dx(), img.Bounds().Dy()\n\tif !validDimensions(width, height) {\n\t\treturn 0, 0, ErrImageTooLarge\n\t}\n\treturn width, height, nil\n}\n\nfunc decodeImage(source []byte) (img image.Image, err error) {\n\tdefer func() {\n\t\tif recovered := recover(); recovered != nil {\n\t\t\timg = nil\n\t\t\terr = fmt.Errorf(\"decode HEIF image: %v\", recovered)\n\t\t}\n\t}()\n\n\tconfig, err := goheic.DecodeConfigBytes(source)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read HEIF image dimensions: %w\", err)\n\t}\n\tif !validDimensions(config.Width, config.Height) {\n\t\treturn nil, ErrImageTooLarge\n\t}\n\n\timg, err = goheic.DecodeBytes(source, goheic.Options{\n\t\tAutoRotate:     true,\n\t\tFrameSizeLimit: maxPixels,\n\t\tThreads:        1,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"decode HEIF image: %w\", err)\n\t}\n\treturn img, nil\n}\n\nfunc validDimensions(width, height int) bool {\n\treturn width > 0 && height > 0 && width <= maxDimension && height <= maxDimension &&","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/heif/convert.go#L168-L204","documentation":"decodeImage wraps a failure from goheic.DecodeConfigBytes (reading just the image header/dimensions) as \"read HEIF image dimensions: %w\". The original goheic error is wrapped with %w so errors.Is/As retain the cause. This fires before full decode, meaning the HEIF container itself could not be parsed even for metadata.","triggerScenarios":"convert or ImageSize is called on bytes that are not a parseable HEIF/HEIC container — wrong format (JPEG/PNG mislabeled .heic), truncated header, or damaged ISOBMFF boxes.","commonSituations":"Files renamed to .heic without conversion, partial downloads/failed transfers, asset corruption on disk or after a bad sync.","solutions":["Verify the file is a genuine HEIF container (magic bytes ftypheic/heix/msf1) before conversion","Re-obtain the asset from its source; the container is unreadable, so content is likely lost","If the file is actually a JPEG/PNG, route it to the correct image path instead of the HEIF pipeline"],"exampleFix":"// before\nw, h, err := heif.ImageSize(data)\nif err != nil { return err }\n// after\nw, h, err := heif.ImageSize(data)\nif err != nil {\n\tvar wrapped error\n\tif errors.As(err, &wrapped) && strings.Contains(err.Error(), \"read HEIF image dimensions\") {\n\t\treturn fmt.Errorf(\"asset is not a valid HEIF container: %v\", err)\n\t}\n\treturn err\n}","handlingStrategy":"try-catch","validationCode":"// check HEIF brand bytes before calling\nif len(data) < 12 || !bytes.Equal(data[4:8], []byte(\"ftyp\")) {\n\treturn fmt.Errorf(\"not a HEIF container\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := heif.ImageSize(data); err != nil {\n\tif strings.Contains(err.Error(), \"read HEIF image dimensions:\") {\n\t\t// container unreadable; %w-wrapped goheic cause available via errors.Unwrap\n\t}\n\treturn err\n}","preventionTips":["Verify file type (magic bytes) before routing assets to the HEIF pipeline","Reject zero-byte or partial downloads at ingest","Use errors.Is/As on the unwrapped cause for precise diagnostics"],"tags":["heif","decoding","corrupt-file"],"backgroundTag":"file-read-failed","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"}