gohugoio/hugo · error

ErrNoConfigFile

ErrNoConfigFile

Error message

Unable to locate config file or config directory. Perhaps you need to create a new project.
       Run `hugo help new` for details.

What it means

The sentinel ErrNoConfigFile, defined in config/allconfig/load.go and returned when Hugo's config loader finds neither a config file (hugo.toml/hugo.yaml/hugo.json or legacy config.*) nor a config/ directory in the working directory. It signals that the directory is not a Hugo project at all, which is why the message suggests creating a new project.

Source

Thrown at config/allconfig/load.go:43

	"github.com/gobwas/glob"
	"github.com/gohugoio/hugo/common/herrors"
	"github.com/gohugoio/hugo/common/hexec"
	"github.com/gohugoio/hugo/common/hmaps"
	"github.com/gohugoio/hugo/common/hugo"
	"github.com/gohugoio/hugo/common/loggers"
	"github.com/gohugoio/hugo/common/paths"
	"github.com/gohugoio/hugo/common/types"
	"github.com/gohugoio/hugo/config"
	"github.com/gohugoio/hugo/helpers"
	hglob "github.com/gohugoio/hugo/hugofs/hglob"
	"github.com/gohugoio/hugo/modules"
	"github.com/gohugoio/hugo/modules/npm"
	"github.com/gohugoio/hugo/parser/metadecoders"
	"github.com/spf13/afero"
)

//lint:ignore ST1005 end user message.
var ErrNoConfigFile = errors.New("Unable to locate config file or config directory. Perhaps you need to create a new project.\n       Run `hugo help new` for details.\n")

func LoadConfig(d ConfigSourceDescriptor) (configs *Configs, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("failed to load config: %v", r)
			debug.PrintStack()
		}
	}()

	if len(d.Environ) == 0 && !hugo.IsRunningAsTest() {
		d.Environ = os.Environ()
	}

	if d.Logger == nil {
		d.Logger = loggers.NewDefault()
	}

	l := &configLoader{ConfigSourceDescriptor: d, cfg: config.New()}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. cd into the actual site directory (the one containing hugo.toml or config/) or pass it with `hugo --source path/to/site`.
  2. If this is a new project, run `hugo new site <name>` to scaffold one — see `hugo help new`.
  3. In CI, set the working directory or -s flag to where the config file is committed.
  4. Check the config file is named hugo.toml/hugo.yaml/hugo.json (or legacy config.*) with a supported extension.

Example fix

# before
cd my-repo && hugo server
# after
cd my-repo && hugo server --source site/
Defensive patterns

Strategy: type-guard

Validate before calling

// Check for a config file before invoking the loader
found := false
for _, name := range []string{"hugo.toml", "hugo.yaml", "hugo.json", "config.toml", "config.yaml", "config.json"} {
    if _, err := os.Stat(filepath.Join(workingDir, name)); err == nil { found = true; break }
}
if _, err := os.Stat(filepath.Join(workingDir, "config")); err == nil { found = true }
if !found {
    return fmt.Errorf("no Hugo config in %s", workingDir)
}

Type guard

func isNoConfigErr(err error) bool {
    return errors.Is(err, allconfig.ErrNoConfigFile)
}

Try / catch

conf, err := allconfig.LoadConfig(opts)
if errors.Is(err, allconfig.ErrNoConfigFile) {
    // distinct, recoverable case: wrong directory or new project
    // prompt the user to run `hugo new site` or pass --source/--config
    return err
}

Prevention

When it happens

Trigger: Running `hugo`, `hugo server`, or most other subcommands from a directory that contains no hugo.toml/hugo.yaml/hugo.json, no config.toml, and no config/ directory; pointing --source/-s at the wrong path; the loader's collectConfigDirs finding zero candidates.

Common situations: Running hugo from the repository root when the site lives in a subdirectory (docs/, site/); CI pipelines with the wrong working-directory; cloning a theme repo (which has no site config) and running hugo in it; a fresh directory before `hugo new site` was ever run; a config file named with an unsupported extension.

Related errors


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