gohugoio/hugo · error

unmarshal of format %q is not supported

Error message

unmarshal of format %q is not supported

What it means

Hugo's metadecoders.Decoder.UnmarshalTo switches on the Format value (ORG, JSON, XML, TOML, YAML, CSV) and returns this error from the default branch when the supplied Format matches none of the supported cases. It exists because Format is derived from a file extension or MIME type upstream, and an unrecognized or zero-value Format must fail fast rather than silently produce empty data.

Source

Thrown at parser/metadecoders/decoder.go:325

			}
			xmlValue = mapValue
		}

		switch v := v.(type) {
		case *map[string]any:
			*v = xmlValue
		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

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Check the file extension or remote Content-Type: it must map to json, toml, yaml/yml, xml, csv, or org.
  2. When using resources.GetRemote, pass an explicit mediaType option or rename/copy the resource with a proper extension before transform.Unmarshal.
  3. If constructing a Decoder in Go code, pass a valid metadecoders.Format constant, not the zero value from a failed FormatFromString lookup.

Example fix

// before
{{ $data := resources.GetRemote "https://example.com/api" | transform.Unmarshal }}
// after
{{ $data := resources.GetRemote "https://example.com/api" (dict "headers" (dict "Accept" "application/json")) | transform.Unmarshal (dict "format" "json") }}
Defensive patterns

Strategy: validation

Validate before calling

// check the format is one of the supported set before calling Unmarshal
var supported = map[metadecoders.Format]bool{metadecoders.JSON: true, metadecoders.YAML: true, metadecoders.TOML: true, metadecoders.CSV: true, metadecoders.XML: true, metadecoders.ORG: true}
if !supported[format] {
    return fmt.Errorf("format %q not supported", format)
}

Type guard

func isSupportedFormat(f metadecoders.Format) bool {
    switch f {
    case metadecoders.JSON, metadecoders.YAML, metadecoders.TOML, metadecoders.CSV, metadecoders.XML, metadecoders.ORG:
        return true
    }
    return false
}

Try / catch

if err := decoder.UnmarshalTo(data, format, &v); err != nil {
    if strings.Contains(err.Error(), "is not supported") {
        // fall back to asking the user for a valid format
    }
    return err
}

Prevention

When it happens

Trigger: Calling Unmarshal/UnmarshalTo with an empty Format (the zero value produced by FormatFromString on an unknown extension), or with a Format constant that has no decode branch. Typically reached via transform.Unmarshal in templates, resources.Get + transform.Unmarshal on a file whose extension isn't json/toml/yaml/yml/xml/csv/org, or data-file loading where the format could not be inferred.

Common situations: Templates piping an unsupported resource (e.g. a .txt, .md, or extensionless remote resource) into transform.Unmarshal; remote resources fetched with resources.GetRemote whose Content-Type/extension doesn't map to a known format so FormatFromString returns ""; typoed extensions like .yamll; expecting Hugo to unmarshal formats it only marshals.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/13d302d890e692a1.json. Report an issue: GitHub ↗.