{"id":"e6299e0dfa80378a","repo":"gohugoio/hugo","slug":"exif-failed-v","errorCode":null,"errorMessage":"exif failed: %v","messagePattern":"exif failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/images/meta/meta.go","lineNumber":219,"sourceCode":"\t}\n\n\treturn d, nil\n}\n\nvar (\n\tisTimeTag = func(s string) bool {\n\t\treturn strings.Contains(s, \"Time\")\n\t}\n\tisGPSTag = func(s string) bool {\n\t\treturn strings.HasPrefix(s, \"GPS\")\n\t}\n)\n\n// Filename is only used for logging.\nfunc (d *Decoder) Decode(filename string, format imagemeta.ImageFormat, r io.Reader) (ex *ExifInfo, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"exif failed: %v\", r)\n\t\t}\n\t}()\n\n\tvar tagInfos imagemeta.Tags\n\thandleTag := func(ti imagemeta.TagInfo) error {\n\t\ttagInfos.Add(ti)\n\t\treturn nil\n\t}\n\n\tshouldHandleTag := func(ti imagemeta.TagInfo) bool {\n\t\tif ti.Source == imagemeta.EXIF {\n\t\t\tif !d.noDate {\n\t\t\t\t// We need the time tags to calculate the date.\n\t\t\t\tif isTimeTag(ti.Tag) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !d.noLatLong {","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/resources/images/meta/meta.go#L201-L237","documentation":"Decoder.Decode in Hugo's image metadata package extracts EXIF data (dates, GPS, tags) from an image via the github.com/gohugoio/imagemeta library. The whole decode runs under a deferred recover(), so this error means the EXIF parser panicked — usually on malformed, truncated, or maliciously crafted EXIF blocks — and Hugo converted the panic into an error instead of crashing the build.","triggerScenarios":"Calling .Exif on an image resource in a template (which drives Decoder.Decode) against a file whose EXIF segment causes a panic in imagemeta — corrupt IFD offsets, truncated files, or unusual maker notes. The recovered panic value is embedded verbatim in the error.","commonSituations":"Photos exported or stripped by buggy tools, images truncated during download/git-lfs mishaps, files renamed to the wrong extension, or edge-case EXIF from unusual cameras/phones. Behavior can change across Hugo versions as the bundled imagemeta version changes.","solutions":["Identify the offending image from the build log and re-export or strip its EXIF (e.g. `exiftool -all= image.jpg`), then rebuild.","Verify the file isn't truncated/corrupt (open it in an image viewer, check its size against the original).","Upgrade Hugo — imagemeta panic fixes land regularly; if it still panics on a valid image, report it upstream with the file."],"exampleFix":"# before: template fails with \"exif failed: ...\" on a corrupt photo\n{{ with .Resources.GetMatch \"photo.jpg\" }}{{ .Exif.Date }}{{ end }}\n# after: strip the broken EXIF block from the asset\nexiftool -all= assets/photo.jpg","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"meta, err := img.Exif()\nif err != nil {\n    log.Printf(\"skipping exif for %s: %v\", img.Name(), err)\n    // proceed without exif rather than failing the build\n}","preventionTips":["Wrap EXIF access in templates with `with`/`try` so images with corrupt EXIF don't break the build","Sanitize or re-encode user-uploaded images before adding them to assets","Set imaging.exif includeFields/excludeFields narrowly to reduce parsing surface","Test the build against images from every camera/source you ingest"],"tags":["hugo","exif","images","metadata","panic-recovery"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}