gohugoio/hugo · error
metadata decoding failed
Error message
metadata decoding failed: %v
What it means
Returned (not panicked) by Decoder.DecodeMeta when the underlying multi-source metadata parser (EXIF + IPTC + XMP) panics. The deferred recover() at meta.go:305 catches the panic and converts it to an error with %v formatting. This is the newer multi-source metadata path, as opposed to the EXIF-only Decode method that produces error 554.
Solutions
- Strip problematic metadata with exiftool: 'exiftool -overwrite_original -all= path/to/image.jpg' then re-add what you need.
- Narrow imaging.meta.sources to only the sources you need — if XMP is causing failures, remove it: sources = ['exif', 'iptc'].
- Re-export the image with a reliable converter to produce clean metadata blocks.
- Use imaging.meta.fields patterns to exclude the specific fields that trigger the panic.
Example fix
# before (hugo.toml) — XMP parsing causes panic on some images [imaging.meta] sources = ["exif", "iptc", "xmp"] # after — drop XMP (the slowest and most failure-prone source) [imaging.meta] sources = ["exif", "iptc"]
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate metadata before Hugo's DecodeMeta // From the shell, check IPTC/XMP integrity: // exiftool -verbose path/to/image.jpg 2>&1 | grep -i 'error|warning' // Or restrict Hugo to EXIF+IPTC only (drop XMP, the most failure-prone): // In hugo.toml: // [imaging.meta] // sources = ["exif", "iptc"]
Try / catch
// DecodeMeta recovers internally and returns an error.
// Handle gracefully:
metaInfo, err := decoder.DecodeMeta(filename, format, reader)
if err != nil {
// err contains 'metadata decoding failed: <panic message>'
log.Printf("warning: metadata decode failed for %s: %v", filename, err)
metaInfo = &MetaInfo{} // proceed without metadata
} Prevention
- Avoid enabling XMP (imaging.meta.sources) unless you need it — it is the slowest and most error-prone source.
- Run 'exiftool -X path/to/image.jpg' to preview the XMP packet before Hugo processes it.
- Note this error uses %v, so it cannot be unwrapped with errors.Unwrap — match on the message prefix instead.
- Test new image sources with a small batch before deploying to a large image set.
When it happens
Trigger: An image with malformed metadata in any of the configured sources (EXIF, IPTC, or XMP) causes the parser to panic during DecodeMeta. This path is used when imaging.meta.sources includes iptc or xmp in addition to exif.
Common situations: Enabling XMP source parsing (imaging.meta.sources = ['exif','iptc','xmp']) on images with corrupt XMP packets; images with IPTC-IIM data that violates the spec; HEIC-to-JPEG conversions that produce malformed XMP RDF.
Related errors
- exif failed
- failed to load image config
- invalid metadata source
- imaging.avif.compression must be one of lossy or lossless…
- imaging.avif.encoderSpeed must be between 1 and 10, got
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/cf8fab3da129ed2e.
Report an issue: GitHub.
Appendix: source
Thrown at resources/images/meta/meta.go:305
tags := make(map[string]any)
for k, v := range tagInfos.All() {
if !d.shouldIncludeField(k) {
continue
}
tags[k] = v.Value
}
ex = &ExifInfo{Lat: lat, Long: long, Date: tm, Tags: tags}
return
}
// DecodeMeta decodes metadata from all sources (EXIF, IPTC, XMP).
// Filename is only used for logging.
func (d *Decoder) DecodeMeta(filename string, format imagemeta.ImageFormat, r io.Reader) (m *MetaInfo, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("metadata decoding failed: %v", r)
}
}()
var tagInfos imagemeta.Tags
handleTag := func(ti imagemeta.TagInfo) error {
tagInfos.Add(ti)
return nil
}
shouldHandleTag := func(ti imagemeta.TagInfo) bool {
// For EXIF, only include tags from IFD0 (skip thumbnail data).
if ti.Source == imagemeta.EXIF {
if !strings.HasPrefix(ti.Namespace, "IFD0") {
return false
}
}
return d.shouldIncludeField(ti.Tag)View on GitHub (pinned to 52c9bd7908)