{"record":{"id":"15ebc1376a07096d","repo":"siyuan-note/siyuan","slug":"errinvalidmode","errorCode":"ErrInvalidMode","errorMessage":"invalid HEIF conversion mode","messagePattern":"invalid HEIF conversion mode","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/heif/convert.go","lineNumber":54,"sourceCode":"\tpreviewQuality   = 90\n\tthumbnailQuality = 85\n\tMaxInputBytes    = 32 * 1024 * 1024\n\tmaxDimension     = 65535\n\tdesktopMaxPixels = 50_000_000\n\tmobileMaxPixels  = 12_500_000\n\t// 解码层仅接受至多 10-bit 4:2:0、无透明通道的单 slice 图像；这里按解码面、CTU 表、\n\t// NRGBA 和一次合并变换预留每像素 16 字节，再单独预留源文件、RBSP 副本与 JPEG 输出。\n\tworkingBytesPerPixel = 16\n\tdesktopWorkingBudget = 960 * 1024 * 1024\n\tmobileWorkingBudget  = 320 * 1024 * 1024\n\tdesktopOutputReserve = 96 * 1024 * 1024\n\tmobileOutputReserve  = 32 * 1024 * 1024\n)\n\nvar (\n\tErrInputTooLarge = errors.New(\"HEIF image exceeds the input size limit\")\n\tErrImageTooLarge = errors.New(\"HEIF image exceeds the dimension limit\")\n\tErrInvalidMode   = errors.New(\"invalid HEIF conversion mode\")\n\n\tconversionSlots = make(chan struct{}, 1)\n\tmaxPixels       = platformMaxPixels()\n)\n\nfunc platformMaxPixels() int {\n\tif runtime.GOOS == \"android\" || runtime.GOOS == \"ios\" {\n\t\treturn pixelsWithinBudget(mobileWorkingBudget, mobileOutputReserve, mobileMaxPixels)\n\t}\n\treturn pixelsWithinBudget(desktopWorkingBudget, desktopOutputReserve, desktopMaxPixels)\n}\n\nfunc ReadFileLimited(path string, maxBytes int64) ([]byte, error) {\n\tif maxBytes <= 0 {\n\t\treturn nil, ErrInputTooLarge\n\t}\n\tfile, err := os.Open(path)\n\tif err != nil {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/heif/convert.go#L36-L72","documentation":"ErrInvalidMode is returned when Options.Mode is neither ModePreview nor ModeThumbnail. GetOrCreate validates the mode before decoding, and convert re-validates it. It is a programming/API-misuse sentinel: only the two exported Mode values are accepted.","triggerScenarios":"Calling heif.GetOrCreate with a zero-value Options{} (Mode is the empty string), or with a custom/typo'd mode string such as \"full\" or \"Preview\" (case-sensitive). Test TestGetOrCreateValidatesOptionsBeforeDecode relies on exactly this sentinel.","commonSituations":"Constructing Options{} partially and forgetting Mode; copying Options from a struct literal that omitted Mode; writing custom mode strings instead of using the heif.ModePreview/ModeThumbnail constants.","solutions":["Always set Options.Mode to heif.ModePreview or heif.ModeThumbnail using the exported constants, never raw strings.","If Options is assembled dynamically, default to ModePreview when unset before calling GetOrCreate.","Check string case and whitespace if the mode is derived from configuration; compare against the constants, not literals."],"exampleFix":"// before\nopts := heif.Options{Encrypted: true, BoxID: box} // Mode zero-value\nres, err := heif.GetOrCreate(ctx, data, opts) // ErrInvalidMode\n// after\nopts := heif.Options{Mode: heif.ModeThumbnail, Encrypted: true, BoxID: box}\nres, err := heif.GetOrCreate(ctx, data, opts)","handlingStrategy":"type-guard","validationCode":"func validMode(m heif.Mode) bool { return m == heif.ModePreview || m == heif.ModeThumbnail }\nif !validMode(opts.Mode) { return errors.New(\"Options.Mode must be heif.ModePreview or heif.ModeThumbnail\") }","typeGuard":"func isConversionMode(m heif.Mode) bool {\n    return m == heif.ModePreview || m == heif.ModeThumbnail\n}","tryCatchPattern":"res, err := heif.GetOrCreate(ctx, data, opts)\nif errors.Is(err, heif.ErrInvalidMode) {\n    opts.Mode = heif.ModePreview // safe default\n    res, err = heif.GetOrCreate(ctx, data, opts)\n}","preventionTips":["Only assign mode values from the exported constants, never raw strings.","Never build Options{} zero-value and call GetOrCreate directly; set Mode explicitly.","Centralize Options construction in one helper so Mode is never forgotten.","Guard with errors.Is(err, heif.ErrInvalidMode) in tests and fallback paths."],"tags":["heif","invalid-argument","enum"],"backgroundTag":"invalid-enum-value","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}