gohugoio/hugo · error

failed to unmarshal config for path

Error message

failed to unmarshal config for path %q: %w

What it means

During Hugo's config-file walk (config/configLoader.go:168), each candidate config file (hugo.toml/yaml/json, params.<lang>.*, menus.<lang>.*, etc.) is decoded into a map via metadecoders.UnmarshalFileToMap. This wraps the decode failure with the offending file path so the user knows exactly which file is malformed. The underlying error is a TOML/YAML/JSON syntax/parse error.

Solutions

  1. Open the exact file named in the error and run it through the matching linter (tomllint / yamllint / a JSON validator).
  2. Read the line/column carried in the wrapped %w error and fix that specific token.
  3. Temporarily comment out the most recently edited section and re-add it incrementally to isolate the bad block.
  4. Ensure you are using the correct format for the file extension (e.g. .toml content must be TOML, not YAML).

Example fix

# before (hugo.toml) -- missing closing bracket
[params
foo = "bar"

# after
[params]
foo = "bar"
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate a config file parses in its declared format before Hugo loads it.
import "github.com/gohugoio/hugo/tpl/internal/go_templates/fmt" // use metadecoders directly:
// ok, err := metadecoders.Default.UnmarshalFileToMap(fs, path)
func ValidateConfigFile(fs afero.Fs, path string) error {
    _, err := metadecoders.Default.UnmarshalFileToMap(fs, path)
    return err
}

Try / catch

// The loader already wraps the parse error with the path; check IsSet + the
// returned err at the call site of LoadConfig.
cfg, err := configLoader.LoadConfig(...)
if err != nil {
    return fmt.Errorf("loading config: %w", err)
}

Prevention

When it happens

Trigger: Any syntax error in a config file under the project or theme config dir: malformed TOML table headers, bad YAML indentation or tabs, unquoted JSON, duplicate keys where forbidden, trailing junk after a value.

Common situations: Hand-editing hugo.toml and leaving an unterminated string or misplaced bracket; copy-pasting YAML with tabs from a browser; a params.en.yaml breaking after a theme/Hugo version upgrade that tightened parsing.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/4bbb04f07cc8de10. Report an issue: GitHub.

Appendix: source

Thrown at config/configLoader.go:172

				return nil
			}

			if fi.IsDir() {
				dirnames = append(dirnames, path)
				return nil
			}

			if !IsValidConfigFilename(path) {
				return nil
			}

			name := paths.Filename(filepath.Base(path))

			item, err := metadecoders.Default.UnmarshalFileToMap(sourceFs, path)
			if err != nil {
				// This will be used in error reporting, use the most specific value.
				dirnames = []string{path}
				return fmt.Errorf("failed to unmarshal config for path %q: %w", path, err)
			}

			var keyPath []string
			var unwrapKey string
			if !DefaultConfigNamesSet[name] {
				// Can be params.jp, menus.en etc.
				name, lang := paths.FileAndExtNoDelimiter(name)
				unwrapKey = name

				keyPath = []string{name}

				if lang != "" {
					keyPath = []string{"languages", lang}
					switch name {
					case "menu", "menus":
						keyPath = append(keyPath, "menus")
					case "params":
						keyPath = append(keyPath, "params")

View on GitHub (pinned to 52c9bd7908)