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

  1. Verify the theme dir exists: `ls themes/<name>`.
  2. Run `hugo mod tidy` then `hugo mod graph` to surface module resolution errors.
  3. Ensure Go is installed and on PATH for Go-module-based themes.
  4. 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

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


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.AllModules

View on GitHub (pinned to 52c9bd7908)