gohugoio/hugo · error

failed to load config

Error message

failed to load config: %w

What it means

Wraps any error from loadConfigMain, the first phase of LoadConfig that locates and parses config files, applies flags, defaults, OS-env overrides, aliases, and computes BaseConfig (workingDir, cacheDir, themesDir). It is the umbrella error for file-level config problems: missing files, TOML/YAML/JSON parse errors, invalid cacheDir from helpers.GetCacheDir.

Solutions

  1. Open the wrapped error: it usually names the file and the line/column of the parse failure.
  2. Validate the config file syntax with a TOML/YAML/JSON linter.
  3. Check any HUGO_* env overrides for malformed values; unset them to isolate.
  4. Confirm `cacheDir`/`workingDir`/`themesDir` resolve to valid paths.

Example fix

# before (TOML duplicate table)
[params]
foo = 1
[params]
bar = 2

# after
[params]
foo = 1
bar = 2
Defensive patterns

Strategy: validation

Validate before calling

# Pre-validate config file syntax with the matching parser
python -c "import tomllib; tomllib.loads(open('hugo.toml').read())" || echo "fix TOML"

Prevention

When it happens

Trigger: A syntax error in hugo.toml/config.yaml; referencing a config file path that exists but fails to parse; `cacheDir` validation failing in helpers.GetCacheDir; an OS-env override (HUGO_*) that produces an unparseable value; an error in applyOsEnvOverrides or applyConfigAliases.

Common situations: A stray tab or unquoted special char in YAML config; a TOML table declared twice; `HUGO_CACHEDIR` pointing somewhere GetCacheDir rejects; merging an old config alias key that no longer maps cleanly.

Related errors


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

Appendix: source

Thrown at config/allconfig/load.go:68

		}
	}()

	if len(d.Environ) == 0 && !hugo.IsRunningAsTest() {
		d.Environ = os.Environ()
	}

	if d.Logger == nil {
		d.Logger = loggers.NewDefault()
	}

	l := &configLoader{ConfigSourceDescriptor: d, cfg: config.New()}
	// Make sure we always do this, even in error situations,
	// as we have commands (e.g. "hugo mod init") that will
	// use a partial configuration to do its job.
	defer l.deleteMergeStrategies()
	res, _, err := l.loadConfigMain(d)
	if err != nil {
		return nil, fmt.Errorf("failed to load config: %w", err)
	}

	configs, err = fromLoadConfigResult(d.Fs, d.Logger, res)
	if err != nil {
		return nil, fmt.Errorf("failed to create config from result: %w", err)
	}

	moduleConfig, modulesClient, err := l.loadModules(configs, d.IgnoreModuleDoesNotExist)
	if err != nil {
		return nil, fmt.Errorf("failed to load modules: %w", err)
	}

	if len(l.ModulesConfigFiles) > 0 {
		// Config merged in from modules.
		// Re-read the config.
		configs, err = fromLoadConfigResult(d.Fs, d.Logger, res)
		if err != nil {
			return nil, fmt.Errorf("failed to create config from modules config: %w", err)

View on GitHub (pinned to 52c9bd7908)