fatedier/frp · error
'.' and '*' are not supported in subdomain
Error message
'.' and '*' are not supported in subdomain
What it means
Server-side validation error from validateDomainConfigForServer: the proxy's subdomain value contains a dot or an asterisk. Subdomains are single labels appended to subDomainHost (e.g. "web" -> web.frps.example.com); dots would create multi-level names that break the wildcard certificate/host mapping, and wildcards are not supported at all. Rejected during frps-side proxy registration validation.
Source
Thrown at pkg/config/v1/validation/proxy.go:98
func validateDomainConfigForServer(c *v1.DomainConfig, s *v1.ServerConfig) error {
subDomainHost := strings.ToLower(s.SubDomainHost)
for _, domain := range c.CustomDomains {
canonicalDomain := strings.ToLower(domain)
if subDomainHost != "" && len(strings.Split(subDomainHost, ".")) < len(strings.Split(canonicalDomain, ".")) {
if strings.HasSuffix(canonicalDomain, "."+subDomainHost) {
return fmt.Errorf("custom domain [%s] should not belong to subdomain host [%s]", domain, s.SubDomainHost)
}
}
}
if c.SubDomain != "" {
if s.SubDomainHost == "" {
return errors.New("subdomain is not supported because this feature is not enabled in server")
}
if strings.Contains(c.SubDomain, ".") || strings.Contains(c.SubDomain, "*") {
return errors.New("'.' and '*' are not supported in subdomain")
}
}
return nil
}
func ValidateProxyConfigurerForClient(c v1.ProxyConfigurer) error {
base := c.GetBaseConfig()
if err := validateProxyBaseConfigForClient(base); err != nil {
return err
}
switch v := c.(type) {
case *v1.TCPProxyConfig:
return validateTCPProxyConfigForClient(v)
case *v1.UDPProxyConfig:
return validateUDPProxyConfigForClient(v)
case *v1.TCPMuxProxyConfig:
return validateTCPMuxProxyConfigForClient(v)View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Use a single label without dots or wildcards: subdomain = "web" (yields web.<subDomainHost>).
- For deeper hostnames (e.g. dev.web.example.com), use customDomains = ["dev.web.example.com"] with DNS pointing at frps.
- For wildcard access, serve customDomains = ["*.web.example.com"] and configure a wildcard TLS certificate on frps (vhost https).
Example fix
# before [[proxies]] name = "web" type = "http" subdomain = "dev.web" # after [[proxies]] name = "web" type = "http" customDomains = ["dev.web.example.com"]
Defensive patterns
Strategy: validation
Validate before calling
func validSubdomainLabel(s string) bool {
return s != "" && !strings.ContainsAny(s, ".*")
}
if !validSubdomainLabel(p.SubDomain) {
return fmt.Errorf("subdomain %q must be a single label without '.' or '*'", p.SubDomain)
} Type guard
func subdomainIsSingleLabel(s string) bool {
return !strings.Contains(s, ".") && !strings.Contains(s, "*")
} Try / catch
if err := validation.ValidateProxyConfigurerForServer(p, serverCfg); err != nil {
if strings.Contains(err.Error(), "'.' and '*' are not supported in subdomain") {
// switch to customDomains for multi-level or wildcard hostnames
}
return err
} Prevention
- Treat subdomain as a single DNS label (letters, digits, hyphen).
- Use customDomains for nested or wildcard hostnames.
- For wildcards, configure a wildcard certificate on frps vhost-https.
When it happens
Trigger: An frpc proxy registers with subdomain = "a.b", subdomain = "*.web", or any value containing '.' or '*' while the server has subDomainHost enabled.
Common situations: Trying to get a nested hostname like dev.web.example.com by writing subdomain = "dev.web" instead of using customDomains; attempting wildcard routing (*.example.com) via subdomain, which requires a wildcard customDomain and matching server cert instead; migrating from another tunnel tool where deep subdomain strings were allowed.
Related errors
- subdomain is not supported because this feature is not enabl
- name should not be empty
- subdomain and custom domains should not be both empty
- failed to parse proxy %s, err: %v
- invalid type [%s]
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/8932bebd682e4eee.
Report an issue: GitHub.