gohugoio/hugo · error
unmarshal failed: %w
Error message
unmarshal failed: %w
What it means
This is the generic wrapper Hugo applies (via toFileError) when the format-specific decoder — json.Unmarshal, toml.Unmarshal, org, or the XML mapper — returns an error in UnmarshalTo. It means the format was recognized but the content is not valid for that format, and the wrapped %w preserves the underlying parser error with file position info where available.
Source
Thrown at parser/metadecoders/decoder.go:332
case *any:
*v = xmlValue
}
case TOML:
err = toml.Unmarshal(data, v)
case YAML:
return UnmarshalYaml(data, v)
case CSV:
return d.unmarshalCSV(data, v)
default:
return fmt.Errorf("unmarshal of format %q is not supported", f)
}
if err == nil {
return nil
}
return toFileError(f, data, fmt.Errorf("unmarshal failed: %w", err))
}
func (d Decoder) unmarshalCSV(data []byte, v any) error {
r := csv.NewReader(bytes.NewReader(data))
r.Comma = d.Delimiter
r.Comment = d.Comment
r.LazyQuotes = d.LazyQuotes
records, err := r.ReadAll()
if err != nil {
return err
}
switch vv := v.(type) {
case *any:
switch d.TargetType {
case "map":
if len(records) < 2 {View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Read the wrapped error — it names the format and usually the line/column — and fix the syntax at that position in the named file.
- Validate the file with an external linter (jq for JSON, a TOML/XML validator) to pinpoint the malformed construct.
- For remote resources, verify the response body actually is the expected format (check for HTML error pages, rate-limit responses) before unmarshalling.
Example fix
// before (data/authors.json)
{
"name": "Jane", // primary author
}
// after
{
"name": "Jane"
} Defensive patterns
Strategy: try-catch
Validate before calling
// cheap syntactic pre-check for JSON input
if format == metadecoders.JSON && !json.Valid(data) {
return errors.New("invalid JSON input")
} Try / catch
if err := decoder.UnmarshalTo(data, format, &v); err != nil {
var typeErr *json.UnmarshalTypeError
if errors.As(err, &typeErr) {
// target type mismatch — fix the destination struct
}
// otherwise the source document is malformed; report file + err
return fmt.Errorf("decode %s: %w", filename, err)
} Prevention
- Treat this as a wrapped error: use errors.As/errors.Is on the unwrapped cause to distinguish syntax errors from type mismatches
- Lint data files (yamllint, jq, taplo) in CI before Hugo consumes them
- Make sure the destination type matches the document shape (map vs slice vs struct)
When it happens
Trigger: Unmarshal of a data file, front matter, or transform.Unmarshal input whose bytes fail the underlying parser: malformed JSON (trailing commas, comments), invalid TOML (bad dates, duplicate keys), broken XML, or org-mode parse failures. YAML and CSV have their own paths, so this branch mostly surfaces JSON/TOML/XML/ORG syntax errors.
Common situations: Hand-edited data/*.json files with trailing commas or comments; TOML front matter with unquoted strings or duplicate keys; remote API responses that return an HTML error page while claiming JSON; merge-conflict markers left in data files; smart quotes pasted from a document into TOML.
Related errors
- failed to detect format from content
- failed to unmarshal XML: %w
- XML root element '%s' has no value
- failed to unmarshal config for path %q: %w
- failed to load config: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/d009fbdd44a6afb0.json.
Report an issue: GitHub ↗.