{"record":{"id":"6642e3463c1c3202","repo":"kataras/iris","slug":"iris-switch-hosts-invalid-target-host-s","errorCode":null,"errorMessage":"iris: switch: hosts: invalid target host: \"%s\"","messagePattern":"iris: switch: hosts: invalid target host: \"(.+?)\"","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/switch_hosts.go","lineNumber":105,"sourceCode":"\t\treturn nil\n\t}\n\n\tswitch target := host.Target.(type) {\n\tcase context.Application:\n\t\treturn target.(*iris.Application)\n\tcase string:\n\t\t// Check if the given target is an application name, if so\n\t\t// we must not redirect (loop) we must serve the request\n\t\t// using that app.\n\t\tif targetApp, ok := context.GetApplication(target); ok {\n\t\t\t// It's always iris.Application so we are totally safe here.\n\t\t\treturn targetApp.(*iris.Application)\n\t\t}\n\t\t// If it's a real host, warn the user of invalid input.\n\t\tu, err := url.Parse(target)\n\t\tif err == nil && u.IsAbs() {\n\t\t\t// remember, we redirect hosts, not full URLs here.\n\t\t\tpanic(fmt.Sprintf(`iris: switch: hosts: invalid target host: \"%s\"`, target))\n\t\t}\n\n\t\tif regex := regexp.MustCompile(host.Pattern); regex.MatchString(target) {\n\t\t\tpanic(fmt.Sprintf(`iris: switch: hosts: loop detected between expression: \"%s\" and target host: \"%s\"`, host.Pattern, host.Target))\n\t\t}\n\n\t\treturn newHostRedirectApp(target, HostsRedirectCode)\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"iris: switch: hosts: invalid target type: %T\", target))\n\t}\n}\n\nfunc hostFilter(expr string) iris.Filter {\n\tregex := regexp.MustCompile(expr)\n\treturn func(ctx iris.Context) bool {\n\t\treturn regex.MatchString(ctx.Host())\n\t}\n}","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/apps/switch_hosts.go#L87-L123","documentation":"When building switch cases from hosts, each target must be a bare host (e.g. \"example.com\"), not a full absolute URL, because the switch redirects between hosts rather than URLs. If the target parses as an absolute URL (has a scheme), hostApp panics with this message. It protects users from confusing host-redirect semantics with URL redirects.","triggerScenarios":"Registering a host entry whose target is \"https://example.com\" or \"http://example.com/path\" instead of \"example.com\"; values read from config that include a scheme.","commonSituations":"Copy-pasting full URLs from a browser; environment variables storing complete site URLs; mixing up SwitchHosts (hosts) with URL redirect handlers.","solutions":["Strip the scheme (and path) from the target so it is just the hostname","Use url.Parse in your own code and pass u.Host to the provider","Store hostnames only in configuration files/env vars"],"exampleFix":"// before\nhosts := iris.Hosts{\"example.com\": \"https://other.com\"}\n// after\nu, _ := url.Parse(\"https://other.com\")\nhosts := iris.Hosts{\"example.com\": u.Host}","handlingStrategy":"validation","validationCode":"for target, app := range hosts {\n\tif u, err := url.Parse(target); err == nil && u.IsAbs() {\n\t\treturn fmt.Errorf(\"host target %q must be a bare host, not a URL\", target)\n\t}\n}","typeGuard":"func isBareHost(target string) bool {\n\tu, err := url.Parse(target)\n\treturn err == nil && !u.IsAbs()\n}","tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tif s, ok := r.(string); ok && strings.Contains(s, \"invalid target host\") {\n\t\t\tlog.Fatalf(\"switch hosts misconfigured: %s\", s)\n\t\t}\n\t\tpanic(r)\n\t}\n}()","preventionTips":["Strip scheme/path from targets before registration (u.Host)","Store hostnames, not URLs, in config","Validate all host targets at config-load time"],"tags":["iris","panic","url-validation","hosts"],"backgroundTag":"invalid-target-host","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}