gohugoio/hugo · error

%q not found

Error message

%q not found

What it means

At modules/collect.go:331, after Hugo has resolved an import to a concrete directory (from a replacement, vendor entry, go module cache, or themesDir), it verifies the directory actually exists on disk. If not, it fails with `%q not found`, wrapped with `ErrNotExist` via `wrapModuleNotFound`. This is a final sanity check that the resolved location is real.

Source

Thrown at modules/collect.go:331

			// Fall back to project/themes/<mymodule>
			if moduleDir == "" {
				var err error
				moduleDir, err = c.createThemeDirname(modulePath, owner.projectMod || moduleImport.pathProjectReplaced)
				if err != nil {
					c.err = err
					return nil, nil
				}
				if found, _ := afero.Exists(c.fs, moduleDir); !found {
					//lint:ignore ST1005 end user message.
					c.err = c.wrapModuleNotFound(fmt.Errorf(`module %q not found in %q; either add it as a Hugo Module or store it in %q.`, modulePath, moduleDir, c.ccfg.ThemesDir))
					return nil, nil
				}
			}
		}
	}

	if found, _ := afero.Exists(c.fs, moduleDir); !found {
		c.err = c.wrapModuleNotFound(fmt.Errorf("%q not found", moduleDir))
		return nil, nil
	}

	if !strings.HasSuffix(moduleDir, fileSeparator) {
		moduleDir += fileSeparator
	}

	ma := &moduleAdapter{
		dir:          moduleDir,
		vendor:       vendored,
		gomod:        mod,
		version:      versionMod,
		versionQuery: requestedVersionQuery,
		// This may be the owner of the _vendor dir
		owner: realOwner,
	}

	if mod == nil {

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Check the quoted path in the error — create it or fix the `module.replacements` mapping that produced it.
  2. If vendored, re-run `hugo mod vendor` (or delete `_vendor`) to regenerate a consistent vendor tree.
  3. Re-download modules with `hugo mod get` if the Go module cache was cleaned.
  4. Avoid absolute machine-specific replacement paths in shared config; use env-specific config or relative paths.

Example fix

# before
[module]
replacements = "github.com/org/theme -> /Users/alice/dev/theme"  # CI has no such dir
# after (relative to project, exists in repo)
[module]
replacements = "github.com/org/theme -> ../theme"
Defensive patterns

Strategy: validation

Validate before calling

if fi, err := os.Stat(mountSource); err != nil || !fi.IsDir() {
    return fmt.Errorf("mount source %q missing", mountSource)
}

Try / catch

if err := collectMounts(); err != nil {
    if strings.Contains(err.Error(), "not found") {
        // a mount source dir or module component is absent
    }
    return err
}

Prevention

When it happens

Trigger: Module collection where the resolved `moduleDir` doesn't exist: a `module.replacements` target pointing at a missing local directory, a stale `_vendor/modules.txt` entry whose files were deleted, or a module-cache path removed by `go clean -modcache`.

Common situations: Replacement directives with machine-specific absolute paths shared across machines/CI; partially committed `_vendor` directories (modules.txt present, files missing); cleaning the Go module cache while Hugo still references cached dirs.

Related errors


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