siyuan-note/siyuan · error

read HEIF image dimensions: %w

Error message

read HEIF image dimensions: %w

What it means

This wraps a failure from goheic.DecodeConfigBytes, which parses only the HEIF headers to obtain width/height without full pixel decode. It means the file's container/box structure could not be parsed for dimensions — the input is not a readable HEIF file. The %w wrap preserves the underlying parse error.

Source

Thrown at kernel/heif/convert.go:186

	}
	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)
	}
	return img, nil
}

func validDimensions(width, height int) bool {
	return width > 0 && height > 0 && width <= maxDimension && height <= maxDimension &&

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Verify the file is genuinely HEIF (ftyp box brand heic/heix/mif1/avif) — check the first bytes
  2. Re-download/re-sync the asset; truncation is the most common cause
  3. Open the file in another viewer to confirm integrity
  4. Convert the image to JPEG/PNG if it is a format variant the parser rejects

Example fix

// before
data, _ := os.ReadFile(path)
w, h, err := heif.ImageSize(data)
// after
data, err := os.ReadFile(path)
if err != nil {
	return 0, 0, err
}
if !looksLikeHeif(data) { // check ftyp brand before calling
	return 0, 0, fmt.Errorf("%s is not a HEIF file", path)
}
w, h, err := heif.ImageSize(data)
Defensive patterns

Strategy: validation

Validate before calling

func isHeifContainer(b []byte) bool {
	if len(b) < 12 || string(b[4:8]) != "ftyp" {
		return false
	}
	brand := string(b[8:12])
	switch brand {
	case "heic", "heix", "mif1", "msf1", "hevc", "avif":
		return true
	}
	return false
}

Type guard

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

Try / catch

if err != nil && strings.Contains(err.Error(), "read HEIF image dimensions") {
	return fmt.Errorf("%w (file is not a readable HEIF container)", err)
}

Prevention

When it happens

Trigger: convert or ImageSize called with bytes that are not valid HEIF: wrong magic (not ftyp heic/heix/avif), truncated file cut inside the meta boxes, or a structurally invalid ISOBMFF container.

Common situations: A JPEG/PNG renamed to .heic; an interrupted upload or sync leaving a truncated file; an exotic HEIF variant (multi-image, uncompressed) the parser does not accept.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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