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
- Open the exact file named in the error and run it through the matching linter (tomllint / yamllint / a JSON validator).
- Read the line/column carried in the wrapped %w error and fix that specific token.
- Temporarily comment out the most recently edited section and re-add it incrementally to isolate the bad block.
- 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
- Run a TOML/YAML/JSON linter on config files in CI.
- Keep one config format per file; match format to extension.
- Avoid tabs in YAML; quote values containing special characters.
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
- failed to decode $_hugo_config in template
- failed to load config
- failed to marshal params
- permalinks configuration invalid: unknown value
- permalinks configuration invalid: unknown value
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)