{"record":{"id":"d20810288f9dfcfd","repo":"tailscale/tailscale","slug":"ts-experimental-dest-dns-name-and-ts-dest-ip-canno","errorCode":null,"errorMessage":"TS_EXPERIMENTAL_DEST_DNS_NAME and TS_DEST_IP cannot both be set","messagePattern":"TS_EXPERIMENTAL_DEST_DNS_NAME and TS_DEST_IP cannot both be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/containerboot/settings.go","lineNumber":263,"sourceCode":"\t\tdir, file := path.Split(s.TailscaledConfigFilePath)\n\t\tif _, err := os.Stat(dir); err != nil {\n\t\t\treturn fmt.Errorf(\"error validating whether directory with tailscaled config file %s exists: %w\", dir, err)\n\t\t}\n\t\tif _, err := os.Stat(s.TailscaledConfigFilePath); err != nil {\n\t\t\treturn fmt.Errorf(\"error validating whether tailscaled config directory %q contains tailscaled config for current capability version %q: %w. If this is a Tailscale Kubernetes operator proxy, please ensure that the version of the operator is not older than the version of the proxy\", dir, file, err)\n\t\t}\n\t\tif _, err := conffile.Load(s.TailscaledConfigFilePath); err != nil {\n\t\t\treturn fmt.Errorf(\"error validating tailscaled configfile contents: %w\", err)\n\t\t}\n\t}\n\tif s.ProxyTargetIP != \"\" && s.UserspaceMode {\n\t\treturn errors.New(\"TS_DEST_IP is not supported with TS_USERSPACE\")\n\t}\n\tif s.ProxyTargetDNSName != \"\" && s.UserspaceMode {\n\t\treturn errors.New(\"TS_EXPERIMENTAL_DEST_DNS_NAME is not supported with TS_USERSPACE\")\n\t}\n\tif s.ProxyTargetDNSName != \"\" && s.ProxyTargetIP != \"\" {\n\t\treturn errors.New(\"TS_EXPERIMENTAL_DEST_DNS_NAME and TS_DEST_IP cannot both be set\")\n\t}\n\tif s.TailnetTargetIP != \"\" && s.UserspaceMode {\n\t\treturn errors.New(\"TS_TAILNET_TARGET_IP is not supported with TS_USERSPACE\")\n\t}\n\tif s.TailnetTargetFQDN != \"\" && s.UserspaceMode {\n\t\treturn errors.New(\"TS_TAILNET_TARGET_FQDN is not supported with TS_USERSPACE\")\n\t}\n\tif s.TailnetTargetFQDN != \"\" && s.TailnetTargetIP != \"\" {\n\t\treturn errors.New(\"Both TS_TAILNET_TARGET_IP and TS_TAILNET_FQDN cannot be set\")\n\t}\n\tif s.TailscaledConfigFilePath != \"\" &&\n\t\t(s.AcceptDNS != nil ||\n\t\t\ts.AuthKey != \"\" ||\n\t\t\ts.Routes != nil ||\n\t\t\ts.ExtraArgs != \"\" ||\n\t\t\ts.Hostname != \"\" ||\n\t\t\ts.ClientID != \"\" ||\n\t\t\ts.ClientSecret != \"\" ||","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/cmd/containerboot/settings.go#L245-L281","documentation":"containerboot settings validation rejects setting both TS_EXPERIMENTAL_DEST_DNS_NAME and TS_DEST_IP. The proxy destination must be specified exactly one way (by IP or by DNS name); two conflicting targets would make forwarding behavior ambiguous, so startup aborts.","triggerScenarios":"A proxy Deployment with both TS_DEST_IP and TS_EXPERIMENTAL_DEST_DNS_NAME set; migrating a manifest from IP-based to DNS-name-based destination without removing the old variable; Helm values that render both keys.","commonSituations":"Copy-paste during migration between destination modes; charts that template both env vars and enable both when values are populated.","solutions":["Decide on one destination mode: keep TS_DEST_IP for a stable IP, or TS_EXPERIMENTAL_DEST_DNS_NAME for a DNS-resolved backend, and delete the other","If the DNS name and IP refer to the same backend, prefer the DNS name for stability across pod restarts","Apply the corrected spec"],"exampleFix":" # before\nenv:\n  - name: TS_DEST_IP\n    value: \"10.24.0.5\"\n  - name: TS_EXPERIMENTAL_DEST_DNS_NAME\n    value: \"backend.default.svc.cluster.local\"\n\n # after\nenv:\n  - name: TS_EXPERIMENTAL_DEST_DNS_NAME\n    value: \"backend.default.svc.cluster.local\"\n  # TS_DEST_IP removed","handlingStrategy":"validation","validationCode":"if [ -n \"$TS_DEST_IP\" ] && [ -n \"$TS_EXPERIMENTAL_DEST_DNS_NAME\" ]; then\n  echo \"invalid config: set only one of TS_DEST_IP or TS_EXPERIMENTAL_DEST_DNS_NAME\" >&2\n  exit 1\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Model destination mode as a single Helm value (dest.ip vs dest.dnsName) that renders exactly one env var","Clean up superseded variables when migrating between modes; empty string can still count as set in some templating stacks","Diff the rendered Pod spec before applying"],"tags":["containerboot","environment-variables","proxy","configuration"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}