{"record":{"id":"cbf8dfa228b5f468","repo":"siyuan-note/siyuan","slug":"avif-exif-data-too-short","errorCode":null,"errorMessage":"avif: exif data too short","messagePattern":"avif: exif data too short","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/heif/internal/h265heic/exif.go","lineNumber":273,"sourceCode":"\n\treturn string(r.data[offset:end])\n}\n\nfunc (r *exifReader) readRational(offset int) float64 {\n\tif offset < 0 || offset+7 >= len(r.data) {\n\t\treturn 0\n\t}\n\tnum, den := r.uint32(offset), r.uint32(offset+4)\n\tif den == 0 {\n\t\treturn 0\n\t}\n\n\treturn float64(num) / float64(den)\n}\n\nfunc parseExifData(data []byte, exif *Exif) error {\n\tif len(data) < 8 {\n\t\treturn errors.New(\"avif: exif data too short\")\n\t}\n\n\tr := &exifReader{data: data}\n\tswitch {\n\tcase data[0] == 'I' && data[1] == 'I':\n\t\tr.littleEndian = true\n\tcase data[0] == 'M' && data[1] == 'M':\n\tdefault:\n\t\treturn errors.New(\"avif: invalid exif byte order marker\")\n\t}\n\n\tif r.uint16(2) != 42 {\n\t\treturn errors.New(\"avif: invalid exif magic number\")\n\t}\n\n\tifdOffset := r.uint32(4)\n\tif ifdOffset < 8 || int(ifdOffset) >= len(data) {\n\t\treturn errors.New(\"avif: invalid exif ifd offset\")","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/heif/internal/h265heic/exif.go#L255-L291","documentation":"parseExifData rejects EXIF payloads shorter than the 8-byte TIFF header (byte-order marker + magic + IFD offset). An EXIF item in the HEIF container must at minimum contain that header; anything shorter cannot be parsed. This is a malformed-metadata condition, not a decode failure of the image pixels.","triggerScenarios":"DecodeExif called on a HEIF/AVIF whose Exif item payload is truncated (0-7 bytes), e.g. the extractor sliced at the wrong offset or the file's meta box declares an Exif item with an empty/tiny body.","commonSituations":"Files edited by tools that strip EXIF but keep the item entry; incorrect item-offset extraction producing a zero-length slice; hand-crafted or fuzzed containers.","solutions":["Treat EXIF as absent and continue — the image itself may still decode fine","Verify the Exif item offset/length extraction from the meta box is correct (off-by-N slicing is the usual culprit)","Re-export the photo with EXIF intact if orientation/GPS metadata matters","If you produce these containers, validate that item extents are non-empty before writing"],"exampleFix":"// before\nexif, err := h265heic.DecodeExif(f)\nif err != nil {\n\treturn fmt.Errorf(\"exif: %w\", err)\n}\n// after\nexif, err := h265heic.DecodeExif(f)\nif err != nil {\n\t// malformed/absent EXIF must not block image display\n\texif = nil\n}","handlingStrategy":"fallback","validationCode":"if exifItem != nil && len(exifItem.Data) < 8 {\n\tlog.Warn(\"EXIF item payload too short; treating as absent\")\n\texifItem = nil\n}","typeGuard":"func hasValidExifHeader(data []byte) bool {\n\treturn len(data) >= 8 && (data[0] == 'I' || data[0] == 'M') && (data[1] == 'I' || data[1] == 'M')\n}","tryCatchPattern":"exif, err := h265heic.DecodeExif(f)\nif err != nil {\n\tlog.Debugf(\"EXIF unavailable: %v\", err)\n\texif = h265heic.DefaultExif() // orientation 1, no GPS\n}","preventionTips":["Never let EXIF parse failures block image display — degrade to defaults","Validate item extent lengths in the meta box before slicing payloads","Assume camera/tool output may strip EXIF and handle its absence everywhere","Verify offset extraction skips any container-added prefix bytes"],"tags":["exif","metadata","truncated-data","heif"],"backgroundTag":"empty-required-field","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}