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

  1. Set target to start with a valid component folder. For frontend assets use target="assets/css" (or "assets/js"), not "css".
  2. Verify source and target are not swapped: source is the real on-disk path, target is the Hugo-internal component location.
  3. 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

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


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)