gohugoio/hugo · error
redirects must have either From or FromRe set
Error message
redirects must have either From or FromRe set
What it means
A hard validation in Server.CompileConfig: every entry in server.Redirects must set at least one of `from` (glob) or `fromRe` (regexp). A redirect with both empty cannot match any path, so Hugo rejects it immediately rather than silently ignoring it.
Solutions
- Add `from = "/old-path/*"` (glob) or `fromRe = "^/old-path/(.*)$"` (regexp) to the offending redirect.
- Remove the redirect entry if it is no longer needed.
- Ensure exactly one matcher style is used per redirect (or both, intentionally).
Example fix
# before [[server.redirects]] to = "/new/" status = 301 # after [[server.redirects]] from = "/old/*" to = "/new/" status = 301
Defensive patterns
Strategy: validation
Validate before calling
python3 - <<'PY'
import tomllib
cfg=tomllib.loads(open('hugo.toml').read())
for r in cfg.get('server',{}).get('redirects',[]):
assert r.get('from') or r.get('fromRe'), f"redirect missing from/fromRe: {r}"
print("redirects ok")
PY Prevention
- Always set `from` (glob) or `fromRe` (regexp) on every redirect.
- Remove placeholder/empty redirect entries.
When it happens
Trigger: A `[[server.redirects]]` block that only sets `to` and `status` but omits both `from` and `fromRe`; a redirect entry created as an empty table.
Common situations: Building a redirect rule and forgetting the source matcher; refactoring redirects and leaving a stub entry.
Related errors
- failed to compile Redirect glob
- failed to compile Redirect header glob
- failed to compile Redirect regexp
- --appendPort=false not supported when in multihost mode
- config needs a filename
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/8cd03d83e7e26ce1.
Report an issue: GitHub.
Appendix: 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 52c9bd7908)