{"record":{"id":"a9705c60b6dae694","repo":"coredns/coredns","slug":"paths-are-not-allowed-in-https-upstream-addresses","errorCode":null,"errorMessage":"paths are not allowed in HTTPS upstream addresses (the /dns-query path is used by default): %s","messagePattern":"paths are not allowed in HTTPS upstream addresses \\(the /dns-query path is used by default\\): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/forward/setup.go","lineNumber":166,"sourceCode":"\t\treturn f, c.ArgErr()\n\t}\n\n\t// Parse block first to get resolver and other options before processing TO addresses.\n\tfor c.NextBlock() {\n\t\tif err := parseBlock(c, f); err != nil {\n\t\t\treturn f, err\n\t\t}\n\t}\n\n\tif f.maxAge > 0 && f.maxAge < f.expire {\n\t\treturn f, fmt.Errorf(\"max_age (%s) must not be less than expire (%s)\", f.maxAge, f.expire)\n\t}\n\n\t// Reject HTTPS upstreams that include a path, the doh implementation default to /dns-query path.\n\tfor _, addr := range to {\n\t\ttrans, h := parse.Transport(addr)\n\t\tif trans == transport.HTTPS && strings.Contains(h, \"/\") {\n\t\t\treturn f, fmt.Errorf(\"paths are not allowed in HTTPS upstream addresses (the /dns-query path is used by default): %s\", addr)\n\t\t}\n\t}\n\n\t// Classify TO addresses in order, preserving config ordering.\n\tentries, err := classifyToAddrs(to)\n\tif err != nil {\n\t\treturn f, err\n\t}\n\tf.toEntries = entries\n\n\t// Expand hostnames and deduplicate globally (first-seen order wins).\n\ttoHosts, err := expandAndDedup(f.toEntries, f.resolver)\n\tif err != nil {\n\t\treturn f, err\n\t}\n\tif len(toHosts) == 0 {\n\t\treturn f, fmt.Errorf(\"no valid upstream addresses found\")\n\t}","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/coredns/coredns/blob/558c9757a92b361e550bdba82d0b4ddf3d12d595/plugin/forward/setup.go#L148-L184","documentation":"The forward plugin's DoH implementation always uses the default /dns-query path, so HTTPS upstream addresses containing a path are rejected at setup. parseStanza iterates the TO addresses, and any address whose transport is HTTPS with a '/' in the host part triggers this error.","triggerScenarios":"Corefile 'forward . https://dns.example.com/dns-query' or any https:// upstream with a trailing/extra path component.","commonSituations":"Copying a DoH URL (with path) from a browser or provider docs into the Corefile; templating the provider's full endpoint URL; confusion between RFC8484 endpoint URLs and CoreDNS's simplified https://host syntax.","solutions":["Strip the path from the HTTPS upstream address, keeping only https://host[:port].","Rely on the plugin's built-in /dns-query default path.","If the provider uses a non-standard path, put a local reverse proxy in front and forward to it without a path."],"exampleFix":"// before\nforward . https://cloudflare-dns.com/dns-query\n// after\nforward . https://cloudflare-dns.com","handlingStrategy":"validation","validationCode":"u, _ := url.Parse(upstream)\nif u.Scheme == \"https\" && (u.Path != \"\" && u.Path != \"/\") {\n    return fmt.Errorf(\"strip path from DoH upstream: %s\", upstream)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store DoH upstreams as bare https://host values, not endpoint URLs.","Trim paths in config pipelines that ingest provider endpoint URLs."],"tags":["configuration","doh","url","coredns"],"backgroundTag":"invalid-url-format","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"}