{"record":{"id":"6c0768529328728f","repo":"gohugoio/hugo","slug":"failed-to-decode-image-s","errorCode":null,"errorMessage":"failed to decode image: %s","messagePattern":"failed to decode image: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/images/mask.go","lineNumber":21,"sourceCode":"import (\n\t\"fmt\"\n\t\"image\"\n\t\"image/color\"\n\t\"image/draw\"\n\n\t\"github.com/gohugoio/gift\"\n)\n\n// maskFilter applies a mask image to a base image.\ntype maskFilter struct {\n\tmask ImageSource\n}\n\n// Draw applies the mask to the base image.\nfunc (f maskFilter) Draw(dst draw.Image, baseImage image.Image, options *gift.Options) {\n\tmaskImage, err := f.mask.DecodeImage()\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"failed to decode image: %s\", err))\n\t}\n\n\t// Ensure the mask is the same size as the base image\n\tbaseBounds := baseImage.Bounds()\n\tmaskBounds := maskImage.Bounds()\n\n\t// Resize mask to match base image size if necessary\n\tif maskBounds.Dx() != baseBounds.Dx() || maskBounds.Dy() != baseBounds.Dy() {\n\t\tg := gift.New(gift.Resize(baseBounds.Dx(), baseBounds.Dy(), gift.LanczosResampling))\n\t\tresizedMask := image.NewRGBA(g.Bounds(maskImage.Bounds()))\n\t\tg.Draw(resizedMask, maskImage)\n\t\tmaskImage = resizedMask\n\t}\n\n\t// Use gift to convert the resized mask to grayscale\n\tg := gift.New(gift.Grayscale())\n\tgrayscaleMask := image.NewGray(g.Bounds(maskImage.Bounds()))\n\tg.Draw(grayscaleMask, maskImage)","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/resources/images/mask.go#L3-L39","documentation":"Thrown by the mask filter's Draw when the mask image source cannot be decoded (mask.go:19-22). DecodeImage returns an error (corrupt file, unsupported format, unreadable resource) and the filter panics, propagating the underlying decode error message.","triggerScenarios":"Calling images.Mask with a resource whose bytes are not a decodable image (wrong format, truncated, zero bytes, or a non-image media type that still passed the ImageSource interface).","commonSituations":"Mask resource path points to a non-image asset; the file is corrupt; remote fetch returned HTML/JSON instead of an image; or the format (e.g. AVIF/HEIC) is not supported by the decoder.","solutions":["Verify the mask resource is a decodable image (PNG/JPEG/GIF/WebP/BMP/TIFF).","Check the resource is non-nil and readable before using it as a mask.","Re-download or replace corrupt mask files."],"exampleFix":"// before\n{{ $mask := resources.Get \"icons/mask.svg\" }}\n{{ $filters = $filters | append (images.Mask $mask) }}\n// after\n{{ $mask := resources.Get \"icons/mask.png\" }}\n{{ $filters = $filters | append (images.Mask $mask) }}","handlingStrategy":"validation","validationCode":"{{ with $mask }}\n  {{ if reflect.IsImageResource . }}\n    {{ $filters = $filters | append (images.Mask .) }}\n  {{ else }}\n    {{ errorf \"mask is not a processable image\" }}\n  {{ end }}\n{{ else }}\n  {{ errorf \"mask resource missing\" }}\n{{ end }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use raster formats (PNG/JPEG) for masks, not SVG.","Verify the resource resolves and is non-empty before masking.","Keep mask assets version-controlled to detect corruption."],"tags":["image-filter","mask","decode","resource-loading","hugo"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}