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

  1. Add a `from` glob (e.g. `from = "/old/**"`) or a `fromRe` regexp to every `[[server.redirects]]` entry.
  2. Check for typos in the key name — it must be exactly `from` or `fromRe` (case-insensitive in TOML decoding).
  3. 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

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


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