{"record":{"id":"8cd42c97ba2ead7b","repo":"siyuan-note/siyuan","slug":"empty-heif-image-8cd42c","errorCode":null,"errorMessage":"empty HEIF image","messagePattern":"empty HEIF image","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/heif/convert.go","lineNumber":103,"sourceCode":"\nfunc pixelsWithinBudget(workingBudget, outputReserve, hardLimit int) int {\n\tavailable := workingBudget - 2*MaxInputBytes - outputReserve\n\tif available <= 0 {\n\t\treturn 0\n\t}\n\treturn min(available/workingBytesPerPixel, hardLimit)\n}\n\ntype Mode string\n\nconst (\n\tModePreview   Mode = \"preview\"\n\tModeThumbnail Mode = \"thumb\"\n)\n\nfunc convert(ctx context.Context, source []byte, mode Mode) ([]byte, error) {\n\tif len(source) == 0 {\n\t\treturn nil, errors.New(\"empty HEIF image\")\n\t}\n\tif len(source) > MaxInputBytes {\n\t\treturn nil, ErrInputTooLarge\n\t}\n\tif mode != ModePreview && mode != ModeThumbnail {\n\t\treturn nil, ErrInvalidMode\n\t}\n\n\tselect {\n\tcase conversionSlots <- struct{}{}:\n\t\tdefer func() {\n\t\t\t<-conversionSlots\n\t\t}()\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\t}\n\tconversionContext, cancel := context.WithTimeout(ctx, conversionTimeout)\n\tdefer cancel()","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/heif/convert.go#L85-L121","documentation":"convert rejects a zero-length source byte slice with the inline error \"empty HEIF image\" before any other validation. It is a fast-fail guard so downstream goheic decoders never see empty input. Not a sentinel — callers must match on the message or check for empty input themselves.","triggerScenarios":"convert (via GetOrCreate or ImageSize callers) is invoked with a nil or empty []byte, e.g. a failed asset read that returned no data and a nil error upstream.","commonSituations":"Asset file read raced with deletion, a truncated download stored as a 0-byte file, passing a slice carved with wrong offsets yielding length 0.","solutions":["Check len(source) == 0 at the call site and handle it as a missing/corrupt asset before invoking HEIF conversion","Fix the upstream reader that produced empty bytes instead of swallowing its error","Treat the empty asset as re-downloadable/re-importable and surface a user-facing message"],"exampleFix":"// before\nout, err := heif.GetOrCreate(ctx, data, opts)\n// after\nif len(data) == 0 {\n\treturn fmt.Errorf(\"asset data is empty, cannot convert HEIF\")\n}\nout, err := heif.GetOrCreate(ctx, data, opts)","handlingStrategy":"validation","validationCode":"if len(data) == 0 {\n\treturn fmt.Errorf(\"empty HEIF asset\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n\tif strings.Contains(err.Error(), \"empty HEIF image\") {\n\t\t// treat as missing/corrupt asset\n\t}\n\treturn err\n}","preventionTips":["Never pass slices that may be nil/empty from failed reads","Make upstream readers return errors instead of empty data","Check asset file size on disk before reading"],"tags":["heif","empty-input","validation"],"backgroundTag":"empty-required-field","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}