siyuan-note/siyuan · error
empty HEIF image
Error message
empty HEIF image
What it means
convert re-checks that the source byte slice is non-empty before decoding, failing with 'empty HEIF image'. This is the lower-level duplicate of the GetOrCreate guard: even direct callers of convert must supply actual image bytes. The checks in convert run in order: emptiness, size limit (ErrInputTooLarge), then mode validity (ErrInvalidMode).
Source
Thrown at kernel/heif/convert.go:103
func pixelsWithinBudget(workingBudget, outputReserve, hardLimit int) int {
available := workingBudget - 2*MaxInputBytes - outputReserve
if available <= 0 {
return 0
}
return min(available/workingBytesPerPixel, hardLimit)
}
type Mode string
const (
ModePreview Mode = "preview"
ModeThumbnail Mode = "thumb"
)
func convert(ctx context.Context, source []byte, mode Mode) ([]byte, error) {
if len(source) == 0 {
return nil, errors.New("empty HEIF image")
}
if len(source) > MaxInputBytes {
return nil, ErrInputTooLarge
}
if mode != ModePreview && mode != ModeThumbnail {
return nil, ErrInvalidMode
}
select {
case conversionSlots <- struct{}{}:
defer func() {
<-conversionSlots
}()
case <-ctx.Done():
return nil, ctx.Err()
}
conversionContext, cancel := context.WithTimeout(ctx, conversionTimeout)
defer cancel()View on GitHub (pinned to 8641553a1f)
Solutions
- Validate len(source) > 0 in the caller before dispatching conversion work to the goroutine.
- Propagate read errors: never send the buffer downstream when the file/asset read failed.
- Route all conversion through heif.GetOrCreate so the unified validation (mode, BoxID, emptiness, size) runs first.
Example fix
// before
go func() { out, err := convert(ctx, buf, mode) }() // buf may be empty
// after
if len(buf) == 0 {
errCh <- errors.New("skip conversion: empty source")
return
}
go func() { out, err := convert(ctx, buf, mode) }() Defensive patterns
Strategy: validation
Validate before calling
if len(buf) == 0 {
return errors.New("refusing conversion: source buffer is empty")
}
if len(buf) > heif.MaxInputBytes {
return heif.ErrInputTooLarge
} Try / catch
out, err := convert(ctx, buf, mode)
if err != nil && strings.Contains(err.Error(), "empty HEIF image") {
return fmt.Errorf("conversion skipped: no image bytes provided: %w", err)
} Prevention
- Check len(source) before dispatching conversion work to goroutines.
- Propagate read errors instead of forwarding empty buffers downstream.
- Prefer heif.GetOrCreate over calling convert directly so all validations run.
- Treat an empty conversion result queue item as a signal to re-fetch the asset.
When it happens
Trigger: Calling the internal convert(ctx, source, mode) with nil/empty source — e.g. an anonymous caller wrapping convert in a goroutine that received an empty buffer from a failed read or an upstream GetOrCreate path whose validation was bypassed.
Common situations: Worker/goroutine pipelines where an empty read result is forwarded to convert without checking len; refactors that add a new entry point into convert without the GetOrCreate pre-validation.
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
- empty HEIF image
- custom emoji file must not be empty
- no valid IDs provided
- encrypted HEIF cache requires a notebook ID
- AI editor input is empty
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/8cd42c97ba2ead7b.
Report an issue: GitHub.