gohugoio/hugo · critical
failed to load config
Error message
failed to load config: %v
What it means
The panic-recovery guard at the top of LoadConfig. A deferred recover() catches any panic during the entire config-loading pipeline and converts it into an error using %v (note: not %w, so the original panic value is stringified, not unwrappable). It also prints the stack trace via debug.PrintStack. This is the catch-all that prevents a raw panic from crashing the process.
Solutions
- Read the printed stack trace to find the panicking file:line and the triggering value.
- If the panic is `unknown type in languages config`, a language entry has a non-Params/non-merge-strategy type; normalize it.
- Reduce config to a minimal repro and report the issue with the stack trace if it looks like an internal bug.
- Update Hugo to the latest patch release in case the panic is a known fixed defect.
Example fix
# before: a language value is a string instead of a table [languages] fr = "french" # after [languages.fr] weight = 20
Defensive patterns
Strategy: try-catch
Try / catch
// Wrap LoadConfig in error handling; panics are already converted to errors
// by Hugo's recover(), so a normal err check suffices.
cfgs, err := allconfig.LoadConfig(d)
if err != nil {
// err.Error() begins with "failed to load config: <panic value>"
// and the stack trace has already been printed to stderr.
return err
} Prevention
- Treat any panic-derived message as a likely internal bug; capture the stack trace.
- Minimize config to a repro before reporting.
- Keep Hugo updated; many panics are fixed in patch releases.
When it happens
Trigger: A nil-pointer dereference or index-out-of-range inside any decoder or helper during config load; an internal assertion failure (e.g. the `panic(fmt.Sprintf("unknown type in languages config: %T", v))` in allconfig.go:1161); a bug in a third-party module hook executed during load.
Common situations: Hitting an internal Hugo bug on an edge-case config; a module/theme whose config triggers an unhandled code path; feeding config values of unexpected Go types (e.g. via mapstructure quirks).
Related errors
- contentNodeToContentNodesPage: unexpected type %T
- DeleteFunc: unknown type %T
- failed to calculate hash for IntSets
- failed to create config
- Insert: unknown type %T
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/7c898951b34eb9c6.
Report an issue: GitHub.
Appendix: source
Thrown at config/allconfig/load.go:48
"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()}
// Make sure we always do this, even in error situations,
// as we have commands (e.g. "hugo mod init") that will
// use a partial configuration to do its job.
defer l.deleteMergeStrategies()
res, _, err := l.loadConfigMain(d)View on GitHub (pinned to 52c9bd7908)