{"record":{"id":"6d59f7836e82dd06","repo":"coredns/coredns","slug":"both-forward-s-and-proxy-level-s-tls-ser","errorCode":null,"errorMessage":"both forward ('%s') and proxy level ('%s') TLS servernames are set for upstream proxy '%s'","messagePattern":"both forward \\('(.+?)'\\) and proxy level \\('(.+?)'\\) TLS servernames are set for upstream proxy '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/forward/setup.go","lineNumber":199,"sourceCode":"\t}\n\tif len(toHosts) == 0 {\n\t\treturn f, fmt.Errorf(\"no valid upstream addresses found\")\n\t}\n\n\ttlsServerNames := make([]string, len(toHosts))\n\tperServerNameProxyCount := make(map[string]int)\n\ttransports := make([]string, len(toHosts))\n\tallowedTrans := map[string]bool{\"dns\": true, \"tls\": true, \"https\": true}\n\tfor i, hostWithZone := range toHosts {\n\t\thost, serverName := splitZone(hostWithZone)\n\t\ttrans, h := parse.Transport(host)\n\n\t\tif !allowedTrans[trans] {\n\t\t\treturn f, fmt.Errorf(\"'%s' is not supported as a destination protocol in forward: %s\", trans, host)\n\t\t}\n\t\tif trans == transport.TLS && serverName != \"\" {\n\t\t\tif f.tlsServerName != \"\" {\n\t\t\t\treturn f, fmt.Errorf(\"both forward ('%s') and proxy level ('%s') TLS servernames are set for upstream proxy '%s'\", f.tlsServerName, serverName, host)\n\t\t\t}\n\n\t\t\ttlsServerNames[i] = serverName\n\t\t\tperServerNameProxyCount[serverName]++\n\t\t}\n\t\tp := proxy.NewProxy(\"forward\", h, trans)\n\t\tf.proxies = append(f.proxies, p)\n\t\ttransports[i] = trans\n\t}\n\n\tperServerNameTlsConfig := make(map[string]*tls.Config)\n\tif f.tlsServerName != \"\" {\n\t\tf.tlsConfig.ServerName = f.tlsServerName\n\t} else {\n\t\tfor serverName, proxyCount := range perServerNameProxyCount {\n\t\t\ttlsConfig := f.tlsConfig.Clone()\n\t\t\ttlsConfig.ServerName = serverName\n\t\t\ttlsConfig.ClientSessionCache = tls.NewLRUClientSessionCache(proxyCount)","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/coredns/coredns/blob/558c9757a92b361e550bdba82d0b4ddf3d12d595/plugin/forward/setup.go#L181-L217","documentation":"For a TLS upstream, the server name may be set either at the forward level (tls_servername option, f.tlsServerName) or per-address via a @servername zone suffix. Setting both is ambiguous, so parseStanza rejects the stanza when a TLS host carries a @serverName while f.tlsServerName is also set.","triggerScenarios":"A forward stanza with 'tls_servername example.com' AND a TO address like 'tls://9.9.9.9@dns.quad9.net' — the two TLS server names conflict for the same upstream.","commonSituations":"Migrating configs and keeping both the legacy per-address suffix and a newer global tls_servername; copy-pasting examples that each use a different mechanism; generated configs that always emit tls_servername while upstream strings retain @suffixes.","solutions":["Remove the @servername suffix from the TO address and keep only the forward-level tls_servername.","Or remove the tls_servername option and use per-address @suffixes for each upstream.","If different upstreams need different names, use only per-address suffixes and drop the global option."],"exampleFix":"// before\nforward . tls://9.9.9.9@dns.quad9.net {\n    tls_servername dns.quad9.net\n}\n// after\nforward . tls://9.9.9.9 {\n    tls_servername dns.quad9.net\n}","handlingStrategy":"validation","validationCode":"if tlsServerNameSet && strings.Contains(upstream, \"@\") {\n    return fmt.Errorf(\"cannot set both tls_servername and @suffix for %s\", upstream)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one TLS server-name mechanism: global tls_servername OR per-address @suffix.","Audit migrated configs for leftover @suffixes."],"tags":["configuration","tls","conflict","coredns"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"558c9757a92b361e550bdba82d0b4ddf3d12d595","analyzedAt":"2026-09-06T22:47:02.106Z","contentChangedAt":"2026-09-06T22:47:02.106Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}