gohugoio/hugo · error
module %q not found in %q; either add it as a Hugo Module or
Error message
module %q not found in %q; either add it as a Hugo Module or store it in %q.
What it means
The primary 'module/theme not found' error. After all resolution paths fail (not a Go module, not downloadable, not in gomods), Hugo falls back to themesDir; if that directory does not exist, wrapModuleNotFound produces this user-facing message naming the module path, the looked-up themesDir path, and the themesDir location to store it. It tells the user the two valid ways to provide a module.
Source
Thrown at modules/collect.go:323
mod = c.gomods.GetByPath(modulePath)
if mod != nil {
moduleDir = mod.Dir
}
}
}
// 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,View on GitHub (pinned to 52c9bd7908)
Solutions
- Clone/install the theme into the themesDir shown in the error: `git clone <url> themes/mytheme`.
- Fix the import path spelling to match the installed folder or the Go module path exactly.
- If themesDir is overridden in config, place the theme under that configured directory.
- For a Go-module theme, ensure Hugo Modules are enabled (`hugo mod get github.com/x/y`) and go is installed.
Example fix
// before (hugo.toml) [[module.imports]] path = "my-them" // typo // after [[module.imports]] path = "my-theme" // and ensure themes/my-theme exists: git clone https://github.com/me/my-theme themes/my-theme
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check: theme folder or Go module must exist before build
import "os"
func ensureThemePresent(themesDir, importPath string) error {
candidate := filepath.Join(themesDir, importPath)
if _, err := os.Stat(candidate); err == nil { return nil }
// not local -> must be a fetchable Go module
return fmt.Errorf("%s missing under %s and not a Go module", importPath, themesDir)
} Type guard
null
Try / catch
// On ErrorContains 'not found in', prompt the user to clone the theme or run `hugo mod get`.
Prevention
- Clone themes into the configured themesDir in your setup script.
- Use --recurse-submodules or `hugo mod get` in CI.
- Double-check import path spelling against the folder/module name.
- Document the themesDir if overridden.
When it happens
Trigger: A `[[module.imports]] path = "mytheme"` where mytheme is neither a resolvable Go module path nor a directory under the configured themesDir (themes/mytheme). Also when module support is disabled (no go.mod/Hugo Modules) and the theme was never placed in themes/.
Common situations: Typo'd theme name, theme cloned into the wrong folder, themesDir overridden in config so themes live elsewhere than expected, missing `git clone` of the theme, or running on a fresh checkout without `--recurse-submodules` / `hugo mod get`.
Related errors
- failed to apply mounts for project: %w
- invalid modules list: %q
- %s: %q: mount source must be a local path for modules/themes
- module does not exist
- invalid module config for %q: both source and target must be
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/daddbded0ba789ae.
Report an issue: GitHub.