gohugoio/hugo · error
failed to load config: %w
Error message
failed to load config: %w
What it means
Wrap returned when l.loadConfigMain fails — the phase that locates, parses and merges the main config file(s), config/ directory, environment overrides and theme configs. It wraps the concrete cause (TOML/YAML/JSON parse error, ErrNoConfigFile, an invalid environment override, a failing section decoder) with a generic 'failed to load config' prefix.
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 8a468df065)
Solutions
- Read the wrapped inner error — it usually includes the file name and line/column of the parse failure; fix that syntax.
- Validate the config file with a TOML/YAML linter matching its extension.
- Unset or fix HUGO_* environment variables if the error appears only in one environment (compare `env | grep HUGO`).
- If using a config/ directory, check every file in config/_default/ and the active environment directory parses on its own.
Example fix
# before (hugo.toml — unclosed string) title = "My Site baseURL = 'https://example.org/' # after title = "My Site" baseURL = 'https://example.org/'
Defensive patterns
Strategy: try-catch
Validate before calling
// If loading from a config dir, verify it exists and is a directory
fi, err := os.Stat(configDir)
if err != nil || !fi.IsDir() {
return fmt.Errorf("config dir %q missing or not a directory", configDir)
} Try / catch
conf, err := allconfig.LoadConfig(opts)
if err != nil {
var fe herrors.FileError
if errors.As(err, &fe) {
// file/line available — show it, don't swallow
}
return err
} Prevention
- Use errors.As with herrors.FileError to extract filename/line for user-facing messages — this one wraps with %w so unwrapping works
- Validate environment-specific config dirs (config/production etc.) in CI, not just the default
- Fail fast on load error; never proceed with a partially-loaded config
When it happens
Trigger: Syntax errors in hugo.toml/hugo.yaml/hugo.json or files under config/_default/; duplicate TOML keys; a HUGO_* environment variable that fails to parse into the expected type; a section decoder from alldecoders.go returning an error during the main merge pass; unreadable config files (permissions).
Common situations: A stray character or unclosed quote after hand-editing config; mixing tabs/spaces in YAML config; CI setting HUGO_PARAMS_* env vars with malformed values; splitting config into config/_default/*.toml and introducing a duplicate or misnamed file.
Related errors
- failed to unmarshal config for path %q: %w
- failed to load translations: %w%s
- failed to parse file %q: %s
- failed to detect format from content
- invalid Highlight option: %s
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/a098f7f1d8d1a21b.json.
Report an issue: GitHub ↗.