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

  1. Add `from = "/old-path/*"` (glob) or `fromRe = "^/old-path/(.*)$"` (regexp) to the offending redirect.
  2. Remove the redirect entry if it is no longer needed.
  3. 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

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


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)