gohugoio/hugo · error

must not be run from the file system root

Error message

must not be run from the file system root

What it means

A safety guard in `hugo mod get ./...` (recursive module update). Before recursively walking the current directory tree looking for `go.mod` files, Hugo checks that the working directory path is at least 5 characters long; a shorter path (e.g. `/`, `C:\`) means you're at or near the filesystem root, and walking from there would scan the whole disk. Hugo aborts rather than risk that.

Source

Thrown at commands/mod.go:272

					}

					var lastArg string
					if len(args) != 0 {
						lastArg = args[len(args)-1]
					}

					if lastArg == "./..." {
						args = args[:len(args)-1]
						// Do a recursive update.
						dirname, err := os.Getwd()
						if err != nil {
							return err
						}

						// Sanity chesimplecobra. We do recursive walking and want to avoid
						// accidents.
						if len(dirname) < 5 {
							return errors.New("must not be run from the file system root")
						}

						filepath.Walk(dirname, func(path string, info os.FileInfo, err error) error {
							if info.IsDir() {
								return nil
							}
							if info.Name() == "go.mod" {
								// Found a module.
								dir := filepath.Dir(path)

								cfg := config.New()
								cfg.Set("workingDir", dir)
								conf, err := r.ConfigFromProvider(configKey{counter: r.configVersionID.Add(1)}, flagsToCfg(cd, cfg))
								if err != nil {
									return err
								}
								r.Println("Update module in", conf.configs.Base.WorkingDir)
								client := conf.configs.ModulesClient

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Change into the actual project directory (the one containing your Hugo modules) before running `hugo mod get ./...`.
  2. In Dockerfiles/CI, set WORKDIR to the project path rather than `/`.
  3. If you only need one module updated, drop `./...` and run `hugo mod get -u` inside that module's directory.

Example fix

# before
cd / && hugo mod get -u ./...
# after
cd /srv/mysite && hugo mod get -u ./...
Defensive patterns

Strategy: validation

Validate before calling

wd, err := os.Getwd()
if err != nil {
    return err
}
if wd == filepath.VolumeName(wd)+string(os.PathSeparator) || wd == "/" {
    return errors.New("run hugo mod from inside the project directory, not /")
}

Type guard

func isFSRoot(dir string) bool {
    return dir == "/" || dir == filepath.VolumeName(dir)+`\`
}

Prevention

When it happens

Trigger: Running `hugo mod get -u ./...` (the recursive form, where the last argument is literally `./...`) with the process's working directory at the filesystem root or another path shorter than 5 characters.

Common situations: Docker containers or CI jobs whose default WORKDIR is `/`, scripts that fail to `cd` into the project before running the recursive module update, or running from a drive root on Windows.

Related errors


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