siyuan-note/siyuan · error

encode image failed

Error message

encode image failed: %s

What it means

Thrown at kernel/util/openai.go:807 when re-encoding a decoded (and possibly resized) PNG or WebP image back to PNG via png.Encode fails. This is rare because PNG encoding of an in-memory NRGBA image seldom fails, but it can happen under memory exhaustion or with zero-size images.

Solutions

  1. Free memory / reduce concurrent image processing, or use a smaller source image
  2. Skip processing and send the original bytes if they are already within the byte limit
  3. Ensure the decoded image has non-zero bounds before encoding
  4. Retry the operation once memory pressure subsides

Example fix

// before: unconditional re-encode on any resize
if needsResize { decoded = imaging.Fit(decoded, maxEdge, maxEdge, imaging.Lanczos) }
out, err := reencodePNGorFail(decoded)
// after: reuse original bytes when no resize is actually needed
if !needsResize {
    return useOriginalBytes(data)
}
decoded = imaging.Fit(decoded, maxEdge, maxEdge, imaging.Lanczos)
out, err := reencodePNGorFail(decoded)
Defensive patterns

Strategy: try-catch

Validate before calling

if decoded.Bounds().Dx() < 1 || decoded.Bounds().Dy() < 1 {
    return errors.New("cannot encode empty image")
}

Try / catch

if err := encodePNG(&output, decoded); err != nil {
    if isOOM(err) {
        // fall back to original bytes or a smaller resize
        return useOriginalOrSmaller(data)
    }
    return err
}

Prevention

When it happens

Trigger: After resizing with imaging.Fit, encoding the resulting image to PNG fails (png.Encode returns a non-nil error) — typically out-of-memory on very large canvases or a degenerate zero-dimension image.

Common situations: Very large images combined with low available memory; images that decode to 0×0 bounds; resource-constrained environments where the encoder cannot allocate buffers.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/946a1fba26e51597. Report an issue: GitHub.

Appendix: source

Thrown at kernel/util/openai.go:807

	bounds := decoded.Bounds()
	needsResize := maxEdge > 0 && (bounds.Dx() > maxEdge || bounds.Dy() > maxEdge)
	if !needsResize && bounds.Dx() == config.Width && bounds.Dy() == config.Height && mimeType != "image/gif" {
		return PreparedImage{
			Data:       data,
			MIMEType:   mimeType,
			Width:      bounds.Dx(),
			Height:     bounds.Dy(),
			SourceSize: len(data),
		}, nil
	}
	if needsResize {
		decoded = imaging.Fit(decoded, maxEdge, maxEdge, imaging.Lanczos)
	}
	bounds = decoded.Bounds()
	if mimeType == "image/png" || mimeType == "image/webp" {
		var output bytes.Buffer
		if err = png.Encode(&output, decoded); err != nil {
			return PreparedImage{}, errors.New("encode image failed: " + err.Error())
		}
		if maxBytes <= 0 || output.Len() <= maxBytes {
			return PreparedImage{
				Data:       output.Bytes(),
				MIMEType:   "image/png",
				Width:      bounds.Dx(),
				Height:     bounds.Dy(),
				SourceSize: len(data),
			}, nil
		}
	}
	var output bytes.Buffer
	if err = jpeg.Encode(&output, decoded, &jpeg.Options{Quality: 92}); err != nil {
		return PreparedImage{}, errors.New("encode image failed: " + err.Error())
	}
	if maxBytes > 0 && output.Len() > maxBytes {
		return PreparedImage{}, fmt.Errorf("prepared image exceeds size limit: %d bytes", maxBytes)
	}

View on GitHub (pinned to 9f775e8a12)