gohugoio/hugo · error
: mount target must be one of
Error message
%s: mount target must be one of: %v
What it means
Thrown by normalizeMounts (modules/collect.go:871) while validating every mount of a module/theme. The first path segment of the mount's 'target' is checked against files.ComponentFolders (archetypes, assets, content, data, i18n, layouts, static); anything else is rejected because Hugo only knows how to route content into those component trees.
Solutions
- Set target to start with a valid component folder. For frontend assets use target="assets/css" (or "assets/js"), not "css".
- Verify source and target are not swapped: source is the real on-disk path, target is the Hugo-internal component location.
- If you need a custom output location, that is configured elsewhere (output formats / publishDir), not via mount target.
Example fix
// before [[module.mounts]] source = "src/css" target = "css" // after [[module.mounts]] source = "src/css" target = "assets/css"
Defensive patterns
Strategy: validation
Validate before calling
// validate mounts before/when configuring Hugo
allowed := map[string]bool{"archetypes":true,"assets":true,"content":true,"data":true,"i18n":true,"layouts":true,"static":true}
for _, m := range cfg.Module.Mounts {
base := strings.SplitN(filepath.ToSlash(filepath.Clean(m.Target)), "/", 2)[0]
if !allowed[base] {
return fmt.Errorf("mount target %q must start with one of %v", m.Target, maps.Keys(allowed))
}
} Prevention
- Always nest custom targets under a valid component folder (e.g. assets/css).
- Treat target as a Hugo-internal path, not a filesystem path.
- Lint your config with a schema/validator before building.
When it happens
Trigger: A [[module.mounts]] entry sets target to a non-component base, e.g. target="css", target="myfolder", or target="public". Also fires when source and target are swapped, putting the filesystem path into target.
Common situations: Typo such as 'asset' instead of 'assets'; assuming target can be any directory; mounting CSS/JS directly to 'css'/'js' instead of nesting under 'assets'; copying a mount example from a tutorial using outdated target names.
Related errors
- failed to init mount
- cannot use --renderToMemory with --destination
- cardinalityThreshold threshold must be between 0 and 100
- failed to compile permalink target
- failed to create baseURL from
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/a9d3b805bd873004.
Report an issue: GitHub.
Appendix: source
Thrown at modules/collect.go:871
_, err := c.fs.Stat(sourceDir)
if err != nil {
continue
}
mnt.Source = sourceDir
} else {
continue
}
}
}
// Verify that target points to one of the predefined component dirs
targetBase := mnt.Target
idxPathSep := strings.Index(mnt.Target, string(os.PathSeparator))
if idxPathSep != -1 {
targetBase = mnt.Target[0:idxPathSep]
}
if !files.IsComponentFolder(targetBase) {
return nil, fmt.Errorf("%s: mount target must be one of: %v", errMsg, files.ComponentFolders)
}
if err := mnt.init(c.logger.Logger()); err != nil {
return nil, fmt.Errorf("%s: %w", errMsg, err)
}
out = append(out, mnt)
}
return out, nil
}
func (c *collector) wrapModuleNotFound(err error) error {
if c.Client.ccfg.IgnoreModuleDoesNotExist {
return nil
}
err = fmt.Errorf(err.Error()+": %w", ErrNotExist)
if c.GoModulesFilename == "" {View on GitHub (pinned to 52c9bd7908)