siyuan-note/siyuan · error

encode HEIF preview: %w

Error message

encode HEIF preview: %w

What it means

This error wraps a failure from Go's image/jpeg encoder while producing the JPEG preview/thumbnail of a decoded HEIF image. jpeg.Encode essentially only fails when the source image contains pixel values outside the encoder's supported representation (e.g. out-of-range or nil image data), so in practice this indicates the decoder returned an image the JPEG encoder cannot serialize. It is an internal conversion-stage failure, not a problem with the input file itself.

Source

Thrown at kernel/heif/convert.go:146

		return nil, ErrImageTooLarge
	}
	if err = conversionContext.Err(); err != nil {
		return nil, err
	}
	if mode == ModeThumbnail && img.Bounds().Dx() > thumbnailWidth {
		img = imaging.Resize(img, thumbnailWidth, 0, imaging.Lanczos)
	}
	if err = conversionContext.Err(); err != nil {
		return nil, err
	}

	quality := previewQuality
	if mode == ModeThumbnail {
		quality = thumbnailQuality
	}
	output := bytes.NewBuffer(make([]byte, 0, estimatedJPEGSize(img)))
	if err = jpeg.Encode(output, img, &jpeg.Options{Quality: quality}); err != nil {
		return nil, fmt.Errorf("encode HEIF preview: %w", err)
	}
	if err = conversionContext.Err(); err != nil {
		return nil, err
	}
	return output.Bytes(), nil
}

func ImageSize(source []byte) (width, height int, err error) {
	if len(source) == 0 {
		return 0, 0, errors.New("empty HEIF image")
	}
	if len(source) > MaxInputBytes {
		return 0, 0, ErrInputTooLarge
	}
	conversionSlots <- struct{}{}
	defer func() {
		<-conversionSlots
	}()

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Re-test with a different HEIF source file to confirm it is file-specific corruption
  2. Check the wrapped cause (%w) to identify the exact jpeg.Encode failure and the image's color model
  3. Update the internal h265heic decoder so decoded images are standard *image.NRGBA/*image.YCbCr before encoding
  4. If a specific photo reproducibly fails, re-export it (e.g. as JPEG) outside the app and re-import

Example fix

// before
img, err := decodeImage(source)
...
if err = jpeg.Encode(output, img, &jpeg.Options{Quality: quality}); err != nil {
	return nil, fmt.Errorf("encode HEIF preview: %w", err)
}
// after
img, err := decodeImage(source)
...
// normalize to a JPEG-safe pixel format before encoding
rgba := image.NewNRGBA(img.Bounds())
draw.Draw(rgba, rgba.Bounds(), img, img.Bounds().Min, draw.Src)
if err = jpeg.Encode(output, rgba, &jpeg.Options{Quality: quality}); err != nil {
	return nil, fmt.Errorf("encode HEIF preview: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if img == nil || img.Bounds().Empty() {
	return errors.New("decoded HEIF image is empty; skip JPEG encoding")
}

Try / catch

if _, err := convert(ctx, data, heif.ModePreview); err != nil {
	if strings.Contains(err.Error(), "encode HEIF preview") {
		log.Warnf("HEIF preview encode failed: %v", err)
		return placeholderPreview
	}
	return err
}

Prevention

When it happens

Trigger: Calling heif convert (via ModePreview or ModeThumbnail paths) on a valid HEIF whose decoded image yields pixel data jpeg.Encode rejects — e.g. a decoded image with color model values outside 0..65535 or a degenerate/empty image buffer.

Common situations: Rare; usually seen after upgrading the internal h265heic decoder so it emits a new pixel format, or with malformed-but-decodable HEIF files producing corrupt pixel buffers. Users encounter it while previewing or thumbnailing HEIC/HEIF photos (e.g. iPhone photos) in SiYuan assets.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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