kataras/iris · error
iris: switch: hosts: loop detected between expression: "%s"
Error message
iris: switch: hosts: loop detected between expression: "%s" and target host: "%s"
What it means
While resolving each host case, hostApp checks whether the target host matches the host's own pattern regex. If it does, registering the case would create an infinite redirect loop (the host redirects to itself), so it panics with a message naming both the expression and the target. This is a startup-time safety check for redirect cycles.
Source
Thrown at apps/switch_hosts.go:109
case context.Application:
return target.(*iris.Application)
case string:
// Check if the given target is an application name, if so
// we must not redirect (loop) we must serve the request
// using that app.
if targetApp, ok := context.GetApplication(target); ok {
// It's always iris.Application so we are totally safe here.
return targetApp.(*iris.Application)
}
// If it's a real host, warn the user of invalid input.
u, err := url.Parse(target)
if err == nil && u.IsAbs() {
// remember, we redirect hosts, not full URLs here.
panic(fmt.Sprintf(`iris: switch: hosts: invalid target host: "%s"`, target))
}
if regex := regexp.MustCompile(host.Pattern); regex.MatchString(target) {
panic(fmt.Sprintf(`iris: switch: hosts: loop detected between expression: "%s" and target host: "%s"`, host.Pattern, host.Target))
}
return newHostRedirectApp(target, HostsRedirectCode)
default:
panic(fmt.Sprintf("iris: switch: hosts: invalid target type: %T", target))
}
}
func hostFilter(expr string) iris.Filter {
regex := regexp.MustCompile(expr)
return func(ctx iris.Context) bool {
return regex.MatchString(ctx.Host())
}
}
// HostsRedirectCode is the default status code is used
// to redirect a matching host to a url.
var HostsRedirectCode = iris.StatusMovedPermanentlyView on GitHub (pinned to 7bedaf55a0)
Solutions
- Narrow the host pattern so it excludes the target host
- Point the target at a different domain than the pattern matches
- Swap the redirect direction (apex → www instead of www → apex) if that was the intent
Example fix
// before
hosts := iris.Hosts{"^(.*\\.)?example.com$": "www.example.com"}
// after
hosts := iris.Hosts{"^example\\.com$": "www.example.com"} Defensive patterns
Strategy: validation
Validate before calling
for pattern, target := range hosts {
if regexp.MustCompile(pattern).MatchString(target) {
return fmt.Errorf("host pattern %q matches its own target %q", pattern, target)
}
} Try / catch
defer func() {
if r := recover(); r != nil {
if s, ok := r.(string); ok && strings.Contains(s, "loop detected") {
log.Fatalf("host redirect loop: %s", s)
}
panic(r)
}
}() Prevention
- Test each host pattern regex against its target before startup
- Avoid overly broad patterns like ".*"
- Prefer anchored patterns (^...$) that exclude the target domain
When it happens
Trigger: Configuring a Hosts entry where the pattern (e.g. "^(.*\.)?example.com$") also matches its own target (e.g. target "www.example.com" under a pattern matching example.com subdomains).
Common situations: Wildcard patterns like ".*" or overly broad regexes paired with a target in the same domain; www → apex redirects written in the wrong direction; config refactors that copy a pattern across entries.
Related errors
- parameter is not alphabetical
- empty regex expression
- iris: switch: empty cases
- iris: switch: hosts: invalid target host: "%s"
- compress: response will not be compressed
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/ec5ab46019859781.
Report an issue: GitHub.