gohugoio/hugo · error

module %q not found

Error message

module %q not found

What it means

In `collector.add` (modules/collect.go:287), when an import has an explicit version query (e.g. `path@v1.2.0`), Hugo calls `downloadModuleVersion`; if that returns no module and no error, Hugo reports `module %q not found`. It means the Go toolchain could not produce a module matching that path at the requested version.

Source

Thrown at modules/collect.go:287

	if moduleDir == "" {
		if requestedVersionQuery == "" {
			mod = c.gomods.GetByPath(modulePath)
			if mod != nil {
				moduleDir = mod.Dir
			}
		}

		if moduleDir == "" {
			if isProbablyModule(modulePath) {
				if requestedVersionQuery != "" {
					var err error
					mod, err = c.downloadModuleVersion(modulePath, requestedVersionQuery)
					if err != nil {
						return nil, err
					}
					if mod == nil {
						return nil, fmt.Errorf("module %q not found", modulePath)
					}
					moduleDir = mod.Dir
					versionMod = mod.Version
				} else if c.GoModulesFilename != "" {
					// See https://golang.org/ref/mod#version-queries
					// This will select the latest release-version (not beta etc.).
					const versionQuery = "upgrade"
					// Try to "go get" it and reload the module configuration.

					// Note that we cannot use c.Get for this, as that may
					// trigger a new module collection and potentially create a infinite loop.
					if err := c.get(fmt.Sprintf("%s@%s", modulePath, versionQuery)); err != nil {
						return nil, err
					}
					if err := c.loadModules(); err != nil {
						return nil, err
					}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Verify the version exists: `go list -m -versions <modulepath>` or check the repo's tags.
  2. For major versions ≥2, use the `/v2` (etc.) suffixed module path.
  3. Remove the version pin to let Hugo select the latest release, then re-pin to a real tag.
  4. If the tag is brand new, retry with `GOPROXY=direct` to bypass a stale proxy cache.

Example fix

# before
[[module.imports]]
path = "github.com/org/theme"
version = "v2.0.0"   # module path for v2 is theme/v2
# after
[[module.imports]]
path = "github.com/org/theme/v2"
version = "v2.0.0"
Defensive patterns

Strategy: validation

Validate before calling

// Check every configured import resolves: entries in config `module.imports`
// must appear in go.mod or exist on disk
for _, imp := range cfg.Imports {
    if !knownModule(imp.Path) { /* fix config or run hugo mod get */ }
}

Try / catch

if err := build(); err != nil {
    if strings.Contains(err.Error(), "not found") {
        // config imports a module absent from go.mod / module cache
    }
    return err
}

Prevention

When it happens

Trigger: An import with `version` set in module config (or a `path@version` reference) where `go` downloads nothing for that path/version combination — nonexistent tag, wrong module path casing, or a version query matching no release.

Common situations: Pinning a theme to a tag that was deleted or never pushed; requesting `v2.x` of a module whose go.mod path lacks the `/v2` suffix; typos in the path; proxy caches missing a very fresh tag.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/280a920c7eeb0599.json. Report an issue: GitHub ↗.