{"record":{"id":"364edb6059a91fda","repo":"caddyserver/caddy","slug":"pki-root-ca-pool-requires-that-a-pki-app-is-config","errorCode":null,"errorMessage":"pki_root CA pool requires that a PKI app is configured: %v","messagePattern":"pki_root CA pool requires that a PKI app is configured: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/capools.go","lineNumber":235,"sourceCode":"\tpool  *x509.CertPool\n\tcerts []*x509.Certificate\n}\n\n// CaddyModule implements caddy.Module.\nfunc (PKIRootCAPool) CaddyModule() caddy.ModuleInfo {\n\treturn caddy.ModuleInfo{\n\t\tID: \"tls.ca_pool.source.pki_root\",\n\t\tNew: func() caddy.Module {\n\t\t\treturn new(PKIRootCAPool)\n\t\t},\n\t}\n}\n\n// Loads the PKI app and load the root certificates into the certificate pool\nfunc (p *PKIRootCAPool) Provision(ctx caddy.Context) error {\n\tpkiApp, err := ctx.AppIfConfigured(\"pki\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"pki_root CA pool requires that a PKI app is configured: %v\", err)\n\t}\n\tpki := pkiApp.(*caddypki.PKI)\n\tfor _, caID := range p.Authority {\n\t\tc, err := pki.GetCA(ctx, caID)\n\t\tif err != nil || c == nil {\n\t\t\treturn fmt.Errorf(\"getting CA %s: %v\", caID, err)\n\t\t}\n\t\tp.ca = append(p.ca, c)\n\t}\n\n\tcaPool := x509.NewCertPool()\n\tvar certs []*x509.Certificate\n\tfor _, ca := range p.ca {\n\t\trootCert := ca.RootCertificate()\n\t\tif rootCert == nil {\n\t\t\treturn fmt.Errorf(\"CA %s has no root certificate\", ca.ID)\n\t\t}\n\t\tcaPool.AddCert(rootCert)","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/capools.go#L217-L253","documentation":"The `tls.ca_pool.source.pki_root` module's Provision() calls ctx.AppIfConfigured(\"pki\"), which errors when the PKI app is not present in the effective Caddy configuration. The pki_root trust pool reads root certificates from Caddy's internal PKI app, so that app must be configured (usually via the `pki` global option or any `internal` issuer usage) before this pool can be provisioned.","triggerScenarios":"Configuring `trust_pool pki_root` (with one or more `ca <id>` entries) in a Caddyfile or JSON config where no PKI app block exists — e.g. no `pki` global option and no site using the `internal` issuer, or the pki app block was removed/renamed while the trust pool remained.","commonSituations":"Copying a client-auth snippet that references pki_root into a minimal test config; upgrading/restructuring a config where the internal CA setup was dropped; using a named CA (e.g. `ca custom`) that was never declared in the pki app.","solutions":["Add a `pki` global option block (or a site/issuer that instantiates the PKI app) to the config, e.g. `{ pki { ca local { name \"My Local CA\" } } }`.","If you do not want Caddy's internal PKI, switch the trust pool to `file`, `inline`, `storage`, or `system` instead of `pki_root`.","Verify the config JSON contains a top-level `\"apps\".\"pki\"` object before applying (`caddy adapt` then inspect)."],"exampleFix":"# before\nexample.com {\n  tls {\n    client_auth {\n      trust_pool pki_root\n    }\n  }\n}\n\n# after\n{\n  pki {\n    ca local {\n      name \"Local CA\"\n    }\n  }\n}\nexample.com {\n  tls {\n    client_auth {\n      trust_pool pki_root\n    }\n  }\n}","handlingStrategy":"validation","validationCode":"// before applying config, confirm the pki app is present\nimport \"encoding/json\"\n\nfunc hasPKIApp(cfgJSON []byte) bool {\n\tvar cfg struct {\n\t\tApps map[string]json.RawMessage `json:\"apps\"`\n\t}\n\tif err := json.Unmarshal(cfgJSON, &cfg); err != nil {\n\t\treturn false\n\t}\n\t_, ok := cfg.Apps[\"pki\"]\n\treturn ok\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the pki global option and any pki_root/pki_intermediate trust pools in the same config source so they are applied atomically.","Run `caddy validate --config Caddyfile --adapter caddyfile` in CI to catch missing-app errors before deploy.","When splitting configs into snippets, grep for pki_root/pki_intermediate usages and ensure a pki app is still adapted."],"tags":["caddy","caddytls","pki","configuration","provisioning"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}