gohugoio/hugo · error
redirects must have either From or FromRe set
Error message
redirects must have either From or FromRe set
What it means
Raised by Server.CompileConfig when a `[[server.redirects]]` entry defines neither `from` (glob) nor `fromRe` (regexp). A redirect with no source pattern can never match anything, so Hugo fails fast at config compile time instead of silently ignoring the rule.
Source
Thrown at config/commonConfig.go:262
}
}
return true
}
func (s *Server) CompileConfig(logger loggers.Logger) error {
if s.compiledHeaders != nil {
return nil
}
for _, h := range s.Headers {
g, err := glob.Compile(h.For)
if err != nil {
return fmt.Errorf("failed to compile Headers glob %q: %w", h.For, err)
}
s.compiledHeaders = append(s.compiledHeaders, g)
}
for _, r := range s.Redirects {
if r.From == "" && r.FromRe == "" {
return fmt.Errorf("redirects must have either From or FromRe set")
}
rd := redirect{
headers: make(map[string]glob.Glob),
}
if r.From != "" {
g, err := glob.Compile(r.From)
if err != nil {
return fmt.Errorf("failed to compile Redirect glob %q: %w", r.From, err)
}
rd.from = g
}
if r.FromRe != "" {
re, err := regexp.Compile(r.FromRe)
if err != nil {
return fmt.Errorf("failed to compile Redirect regexp %q: %w", r.FromRe, err)
}
rd.fromRe = re
}View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Add a `from` glob (e.g. `from = "/old/**"`) or a `fromRe` regexp to every `[[server.redirects]]` entry.
- Check for typos in the key name — it must be exactly `from` or `fromRe` (case-insensitive in TOML decoding).
- Delete empty placeholder redirect blocks from the config.
Example fix
# before (hugo.toml) [[server.redirects]] to = "/new/" status = 301 # after [[server.redirects]] from = "/old/**" to = "/new/" status = 301
Defensive patterns
Strategy: validation
Validate before calling
for i, r := range cfg.Server.Redirects {
if r.From == "" && r.FromRe == "" {
return fmt.Errorf("server.redirects[%d]: set either 'from' (glob) or 'fromRe' (regexp)", i)
}
} Try / catch
if err := cfg.Server.CompileConfig(logger); err != nil {
if strings.Contains(err.Error(), "redirects must have either From or FromRe") {
// a [[server.redirects]] block is missing its matcher key
}
return err
} Prevention
- Every [[server.redirects]] entry needs `from` or `fromRe` — watch for typos like `From =` vs `from =` in the wrong table, or an empty string
- When converting Netlify _redirects to hugo.toml, verify each rule got a matcher
- Keep redirects in one place and validate with `hugo server` after edits
When it happens
Trigger: Declaring a `[[server.redirects]]` block containing only `to`/`status`/`force` keys, or misspelling the source key (e.g. `From = "..."` typoed as `form`, or using `source =` from Netlify syntax), leaving both From and FromRe empty when the map is decoded.
Common situations: Porting `_redirects`/netlify.toml rules (which use `from`/`source` differently) into Hugo's server config; leaving a placeholder redirect block while scaffolding; YAML/TOML indentation errors that detach `from` from the redirect entry; upgrading configs where `fromRe` was added (Hugo 0.112+) and mixing up key names.
Related errors
- failed to compile Redirect glob %q: %w
- failed to compile Redirect regexp %q: %w
- failed to compile Redirect header glob %q: %w
- failed to compile Headers glob %q: %w
- failed to create config from result: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/8cd03d83e7e26ce1.json.
Report an issue: GitHub ↗.