gohugoio/hugo · error
failed to load modules
Error message
failed to load modules: %w
What it means
Wraps failures from configLoader.loadModules, which builds a modules.Client and calls Collect(). This resolves the project module, mounts, theme modules, Hugo Modules via Go (go.mod), and runs the HookBeforeFinalize that merges each module's config into the root. Failures include missing theme dir, module not found, go command unavailable, module import cycles, or errors while merging module config.
Solutions
- Verify the theme dir exists: `ls themes/<name>`.
- Run `hugo mod tidy` then `hugo mod graph` to surface module resolution errors.
- Ensure Go is installed and on PATH for Go-module-based themes.
- Set IgnoreModuleDoesNotExist if a missing optional module is expected.
Example fix
# before theme = "missing-theme" # after theme = "my-theme" # matches themes/my-theme
Defensive patterns
Strategy: validation
Validate before calling
# Confirm theme dir and Go toolchain exist [ -d "themes/$THEME" ] && echo "theme ok" || echo "theme missing" command -v go >/dev/null && echo "go ok" || echo "go missing"
Prevention
- Run `hugo mod tidy` after pulling.
- Pin theme/module versions in go.mod or module imports.
- Ensure Go is installed for Go-module-based themes.
When it happens
Trigger: `theme = "mytheme"` pointing at a non-existent themes/ entry; `[[module.imports]]` with a path/git URL that can't be resolved; Go toolchain missing when Go modules are used; a module whose config fails to merge; IgnoreModuleDoesNotExist=false and a referenced module is absent.
Common situations: Cloning a repo without `--recurse-submodules` or running `hugo mod tidy`; theme renamed/moved; vendored modules out of date; CI missing Go installation; a private module needing GOPRIVATE/GONOSUMCHECK setup.
Related errors
- failed to create config from modules config
- cannot vendor module
- could not determine content directory for
- failed to apply mounts for project
- failed to get
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/28dbc8aa03484b02.
Report an issue: GitHub.
Appendix: source
Thrown at config/allconfig/load.go:78
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)
}
if err := configs.transientErr(); err != nil {
return nil, fmt.Errorf("failed to create config from modules config: %w", err)
}
configs.LoadingInfo.ConfigFiles = append(configs.LoadingInfo.ConfigFiles, l.ModulesConfigFiles...)
} else if err := configs.transientErr(); err != nil {
return nil, fmt.Errorf("failed to create config: %w", err)
}
configs.Modules = moduleConfig.AllModulesView on GitHub (pinned to 52c9bd7908)