{"record":{"id":"ad46e59647613a3e","repo":"caddyserver/caddy","slug":"subject-does-not-qualify-for-certificate-s","errorCode":null,"errorMessage":"subject does not qualify for certificate: '%s'","messagePattern":"subject does not qualify for certificate: '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/httpcaddyfile/tlsapp.go","lineNumber":255,"sourceCode":"\n\t\t\t// associate our new automation policy with this server block's hosts\n\t\t\tap.SubjectsRaw = hostsNotHTTP\n\n\t\t\t// if a combination of public and internal names were given\n\t\t\t// for this same server block and no issuer was specified, we\n\t\t\t// need to separate them out in the automation policies so\n\t\t\t// that the internal names can use the internal issuer and\n\t\t\t// the other names can use the default/public/ACME issuer\n\t\t\tvar ap2 *caddytls.AutomationPolicy\n\t\t\tif len(ap.Issuers) == 0 {\n\t\t\t\tvar internal, external []string\n\t\t\t\tfor _, s := range ap.SubjectsRaw {\n\t\t\t\t\t// do not create Issuers for Tailscale domains; they will be given a Manager instead\n\t\t\t\t\tif isTailscaleDomain(s) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tif !certmagic.SubjectQualifiesForCert(s) {\n\t\t\t\t\t\treturn nil, warnings, fmt.Errorf(\"subject does not qualify for certificate: '%s'\", s)\n\t\t\t\t\t}\n\t\t\t\t\t// we don't use certmagic.SubjectQualifiesForPublicCert() because of one nuance:\n\t\t\t\t\t// names like *.*.tld that may not qualify for a public certificate are actually\n\t\t\t\t\t// fine when used with OnDemand, since OnDemand (currently) does not obtain\n\t\t\t\t\t// wildcards (if it ever does, there will be a separate config option to enable\n\t\t\t\t\t// it that we would need to check here) since the hostname is known at handshake;\n\t\t\t\t\t// and it is unexpected to switch to internal issuer when the user wants to get\n\t\t\t\t\t// regular certificates on-demand for a class of certs like *.*.tld.\n\t\t\t\t\tif subjectQualifiesForPublicCert(ap, s) {\n\t\t\t\t\t\texternal = append(external, s)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tinternal = append(internal, s)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif len(external) > 0 && len(internal) > 0 {\n\t\t\t\t\tap.SubjectsRaw = external\n\t\t\t\t\tapCopy := *ap\n\t\t\t\t\tap2 = &apCopy","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/httpcaddyfile/tlsapp.go#L237-L273","documentation":"While splitting automation policy subjects into internal vs public issuer groups, each subject (except Tailscale domains) is checked with certmagic.SubjectQualifiesForCert. Names that cannot be in any certificate — empty strings, names with spaces, IPs with a port, a bare '*', over-253-char names, dotless names where disallowed — are rejected here during adaptation.","triggerScenarios":"A site address or tls subject like 'my site.com' (space), 'localhost:3000' leaking the port into the TLS subject, a bare '*' label, 'bad..name' double dots, or a malformed placeholder-expanded hostname.","commonSituations":"Env-var/placeholder-expanded hostnames coming out empty or malformed; copying URLs (with scheme or port) instead of bare hostnames into site addresses; typos creating double dots or trailing spaces.","solutions":["Fix the reported subject (printed in quotes in the error) to be a valid DNS name or IP without port/scheme/spaces.","If you need an internal-only name, ensure it still qualifies (use 'foo.internal' — not empty, not bare '*', no port).","Check what your placeholders/env vars actually expand to at adapt time."],"exampleFix":"# before\nhttps://example.com:8443 {\n  tls internal\n}\n\n# after\nexample.com:8443 {\n  tls internal\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use bare hostnames (no scheme, no port) as site addresses; let Caddy derive the TLS subject.","Lint generated/host-provisioned hostnames for emptiness, spaces, ports, and double dots."],"tags":["caddyfile","tls","certmagic","hostname-validation"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}