siyuan-note/siyuan · error

decode HEIF image: %v

Error message

decode HEIF image: %v

What it means

decodeImage recovers a panic from the internal HEIC decoder (which wraps cgo/libheif-style native code) and converts it into this error carrying the recovered value. Native decoders can panic (or crash) on malformed bitstreams, so the package deliberately converts panics into ordinary errors to protect the process.

Source

Thrown at kernel/heif/convert.go:180

	defer func() {
		<-conversionSlots
	}()
	img, err := decodeImage(source)
	if err != nil {
		return 0, 0, err
	}
	width, height = img.Bounds().Dx(), img.Bounds().Dy()
	if !validDimensions(width, height) {
		return 0, 0, ErrImageTooLarge
	}
	return width, height, nil
}

func decodeImage(source []byte) (img image.Image, err error) {
	defer func() {
		if recovered := recover(); recovered != nil {
			img = nil
			err = fmt.Errorf("decode HEIF image: %v", recovered)
		}
	}()

	config, err := goheic.DecodeConfigBytes(source)
	if err != nil {
		return nil, fmt.Errorf("read HEIF image dimensions: %w", err)
	}
	if !validDimensions(config.Width, config.Height) {
		return nil, ErrImageTooLarge
	}

	img, err = goheic.DecodeBytes(source, goheic.Options{
		AutoRotate:     true,
		FrameSizeLimit: maxPixels,
		Threads:        1,
	})
	if err != nil {
		return nil, fmt.Errorf("decode HEIF image: %w", err)

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Treat the file as unrenderable and surface a user-facing 'cannot open this image' message
  2. Check the recovered value in the message to see whether it is an out-of-range panic, nil deref, or native assertion
  3. Verify the file opens in another HEIF viewer; if not, the file is corrupt
  4. Report the file to maintainers if it decodes elsewhere — it may expose a decoder bug needing an upstream fix
  5. Consider re-encoding the image with an external tool before importing
Defensive patterns

Strategy: try-catch

Validate before calling

if len(source) < 12 || string(source[4:8]) != "ftyp" {
	return errors.New("not a HEIF container")
}

Type guard

func looksLikeHeif(b []byte) bool {
	return len(b) >= 12 && string(b[4:8]) == "ftyp"
}

Try / catch

if err != nil && strings.HasPrefix(err.Error(), "decode HEIF image:") {
	log.Warnf("decoder panicked on HEIF input: %v", err)
	return errUnsupportedFile
}

Prevention

When it happens

Trigger: Any call path that reaches decodeImage — convert (ModePreview/ModeThumbnail) or ImageSize — where the internal decoder panics while parsing the HEIF/HEVC bitstream, e.g. malformed NAL units, corrupt VPS/SPS/PPS, or out-of-bounds access in native parsing.

Common situations: Corrupt or deliberately fuzzed .heic files; partially downloaded/truncated assets; files renamed to .heic that are not actually HEIF; unusual HEVC profiles the decoder mishandles.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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