gohugoio/hugo · error
invalid module config for %q: both source and target must be
Error message
invalid module config for %q: both source and target must be set
What it means
Returned by collector.normalizeMounts in modules/collect.go:800 when a module mount has an empty Source or Target. Mounts map a source path into Hugo's virtual filesystem; both ends are mandatory. The error names the offending module (owner.Path()).
Source
Thrown at modules/collect.go:800
return s
}
if strings.HasPrefix(s, "../../node_modules/") {
// See #14083. This was a common construct to mount node_modules from the project root.
// This started failing in v0.152.0 when we tightened the validation.
return strings.TrimPrefix(s, "../../")
}
return ""
}
func (c *collector) normalizeMounts(owner *moduleAdapter, mounts []Mount) ([]Mount, error) {
var out []Mount
dir := owner.Dir()
for _, mnt := range mounts {
errMsg := fmt.Sprintf("invalid module config for %q", owner.Path())
if mnt.Source == "" || mnt.Target == "" {
return nil, errors.New(errMsg + ": both source and target must be set")
}
// Special case for node_modules imports in themes/modules.
// See #14089.
var isModuleNodeModulesImport bool
if !owner.projectMod {
nodeModulesImportSource := c.nodeModulesRoot(mnt.Source)
if nodeModulesImportSource != "" {
isModuleNodeModulesImport = true
mnt.Source = nodeModulesImportSource
}
}
mnt.Source = filepath.Clean(mnt.Source)
mnt.Target = filepath.Clean(mnt.Target)
var sourceDir string
if !owner.projectMod && !filepath.IsLocal(mnt.Source) {View on GitHub (pinned to 52c9bd7908)
Solutions
- Find the mount flagged by the module name in the error and add the missing source and target.
- Ensure source is a non-empty path relative to the module dir and target is a Hugo filesystem dir (e.g. static, content, layouts, assets, archetypes, i18n, data).
- Run `hugo config` to print resolved mounts and spot the blank entry.
Example fix
// before [[module.mounts]] source = "content" // after [[module.mounts]] source = "content" target = "content"
Defensive patterns
Strategy: validation
Validate before calling
// Validate every mount has both fields before collection.
for _, m := range mounts {
if m.Source == "" || m.Target == "" { return errors.New("mount missing source/target") }
} Prevention
- Always set both source and target on [[module.mounts]].
- Validate mounts via `hugo config` after edits.
- Treat a missing field as a schema error in config generation.
When it happens
Trigger: Declaring [[module.mounts]] with source or target omitted/blank, in either the project config or a theme/module's config. normalizeMounts runs during module collection for every mount of every active module.
Common situations: A typo'd [[module.mounts]] table missing a key, a config merge that dropped a field, or a theme upgrade whose mounts schema expects a field the project didn't supply.
Related errors
- could not determine content directory for %q
- cannot vendor module %q, need at least one mount
- failed to apply mounts for project: %w
- %s: %q: mount source must be a local path for modules/themes
- role name cannot be empty
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/df0f22abf300c538.
Report an issue: GitHub.