gohugoio/hugo · error
invalid metadata source
Error message
invalid metadata source %q in imaging.meta.sources config; must be one of %s
What it means
Validates each entry in imaging.meta.sources after lowercasing. The only allowed values are 'exif', 'iptc', and 'xmp' (defined in the validMetaSources map). The error message lists all valid keys, sorted alphabetically. This controls which metadata standards Hugo extracts from images.
Solutions
- Check the error message — it prints the invalid source and the sorted list of valid sources.
- Fix imaging.meta.sources in hugo.toml to contain only values from {exif, iptc, xmp}.
- Remove the sources key to use the default of ['exif', 'iptc'] (XMP is excluded by default for performance).
Example fix
# before (hugo.toml) [imaging.meta] sources = ["exif", "iptc", "tiff"] # after [imaging.meta] sources = ["exif", "iptc", "xmp"]
Defensive patterns
Strategy: validation
Validate before calling
// Validate metadata sources before decoding
func validateMetaSources(sources []string) error {
valid := map[string]bool{"exif": true, "iptc": true, "xmp": true}
for _, s := range sources {
if !valid[strings.ToLower(s)] {
return fmt.Errorf("invalid metadata source %q; valid: exif, iptc, xmp", s)
}
}
return nil
} Prevention
- Stick to the default ['exif', 'iptc'] — XMP is slower and more prone to parsing issues.
- Values are case-insensitive but lowercase is conventional.
- Only add 'xmp' if your templates actually use XMP-derived metadata fields.
When it happens
Trigger: Setting imaging.meta.sources in hugo.toml to a list containing any string other than exif, iptc, or xmp (case-insensitive, since values are normalized to lowercase before checking).
Common situations: Typing 'EXIF' in uppercase (harmless — normalized), 'tiff' or 'raw' (not supported), or 'rdf' (confusing XMP's underlying format with the source name). Also from copying an example that references a source removed or renamed in a newer Hugo version.
Related errors
- exif failed
- imaging.avif.compression must be one of lossy or lossless…
- imaging.avif.encoderSpeed must be between 1 and 10, got
- imaging.avif.hint must be one of picture, photo, drawing…
- imaging.avif.quality must be between 1 and 100 inclusive…
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/de177fb893a2ca82.
Report an issue: GitHub.
Appendix: source
Thrown at resources/images/config.go:607
if len(cfg.Meta.Fields) == 0 {
// Default: include all fields except technical metadata.
// Don't change this for no good reason. Please don't.
cfg.Meta.Fields = []string{
"! *{GPS,Exif,Exposure[MPB],Contrast,Resolution,Sharp,JPEG,Metering,Sensing,Saturation,ColorSpace,Flash,WhiteBalance}*",
}
}
if len(cfg.Meta.Sources) == 0 {
// Default to EXIF and IPTC (XMP is slower to decode).
cfg.Meta.Sources = []string{"exif", "iptc"}
} else {
// Normalize to lowercase.
for i, s := range cfg.Meta.Sources {
cfg.Meta.Sources[i] = strings.ToLower(s)
if !validMetaSources[cfg.Meta.Sources[i]] {
keys := slices.Collect(maps.Keys(validMetaSources))
slices.Sort(keys)
return fmt.Errorf("invalid metadata source %q in imaging.meta.sources config; must be one of %s", s, keys)
}
}
}
return nil
}
type ExifConfig struct {
// Regexp matching the Exif fields you want from the (massive) set of Exif info
// available. As we cache this info to disk, this is for performance and
// disk space reasons more than anything.
// If you want it all, put ".*" in this config setting.
// Note that if neither this or ExcludeFields is set, Hugo will return a small
// default set.
IncludeFields string
// Regexp matching the Exif fields you want to exclude. This may be easier to use
// than IncludeFields above, depending on what you want.View on GitHub (pinned to 52c9bd7908)