siyuan-note/siyuan · warning

avif: exif data too short

Error message

avif: exif data too short

What it means

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.

Source

Thrown at kernel/heif/internal/h265heic/exif.go:273

	return string(r.data[offset:end])
}

func (r *exifReader) readRational(offset int) float64 {
	if offset < 0 || offset+7 >= len(r.data) {
		return 0
	}
	num, den := r.uint32(offset), r.uint32(offset+4)
	if den == 0 {
		return 0
	}

	return float64(num) / float64(den)
}

func parseExifData(data []byte, exif *Exif) error {
	if len(data) < 8 {
		return errors.New("avif: exif data too short")
	}

	r := &exifReader{data: data}
	switch {
	case data[0] == 'I' && data[1] == 'I':
		r.littleEndian = true
	case data[0] == 'M' && data[1] == 'M':
	default:
		return errors.New("avif: invalid exif byte order marker")
	}

	if r.uint16(2) != 42 {
		return errors.New("avif: invalid exif magic number")
	}

	ifdOffset := r.uint32(4)
	if ifdOffset < 8 || int(ifdOffset) >= len(data) {
		return errors.New("avif: invalid exif ifd offset")

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Treat EXIF as absent and continue — the image itself may still decode fine
  2. Verify the Exif item offset/length extraction from the meta box is correct (off-by-N slicing is the usual culprit)
  3. Re-export the photo with EXIF intact if orientation/GPS metadata matters
  4. If you produce these containers, validate that item extents are non-empty before writing

Example fix

// before
exif, err := h265heic.DecodeExif(f)
if err != nil {
	return fmt.Errorf("exif: %w", err)
}
// after
exif, err := h265heic.DecodeExif(f)
if err != nil {
	// malformed/absent EXIF must not block image display
	exif = nil
}
Defensive patterns

Strategy: fallback

Validate before calling

if exifItem != nil && len(exifItem.Data) < 8 {
	log.Warn("EXIF item payload too short; treating as absent")
	exifItem = nil
}

Type guard

func hasValidExifHeader(data []byte) bool {
	return len(data) >= 8 && (data[0] == 'I' || data[0] == 'M') && (data[1] == 'I' || data[1] == 'M')
}

Try / catch

exif, err := h265heic.DecodeExif(f)
if err != nil {
	log.Debugf("EXIF unavailable: %v", err)
	exif = h265heic.DefaultExif() // orientation 1, no GPS
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/cbf8dfa228b5f468. Report an issue: GitHub.