{"record":{"id":"fd9e863a4e882819","repo":"caddyserver/caddy","slug":"error-loading-cert-s-from-storage-s","errorCode":null,"errorMessage":"error loading cert '%s' from storage: %s","messagePattern":"error loading cert '(.+?)' from storage: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/capools.go","lineNumber":429,"sourceCode":"\t\t}\n\t\tcmStorage, err := val.(caddy.StorageConverter).CertMagicStorage()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"creating storage configuration: %v\", err)\n\t\t}\n\t\tca.storage = cmStorage\n\t}\n\tif ca.storage == nil {\n\t\tca.storage = ctx.Storage()\n\t}\n\tif len(ca.PEMKeys) == 0 {\n\t\treturn fmt.Errorf(\"no PEM keys specified\")\n\t}\n\tcaPool := x509.NewCertPool()\n\tvar certs []*x509.Certificate\n\tfor _, caID := range ca.PEMKeys {\n\t\tbs, err := ca.storage.Load(ctx, caID)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error loading cert '%s' from storage: %s\", caID, err)\n\t\t}\n\t\t// Parse PEM to extract certificates\n\t\tpemData := bs\n\t\tfor len(pemData) > 0 {\n\t\t\tvar block *pem.Block\n\t\t\tblock, pemData = pem.Decode(pemData)\n\t\t\tif block == nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif block.Type != \"CERTIFICATE\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcert, err := x509.ParseCertificate(block.Bytes)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"parsing certificate '%s': %v\", caID, err)\n\t\t\t}\n\t\t\tcaPool.AddCert(cert)\n\t\t\tcerts = append(certs, cert)","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/capools.go#L411-L447","documentation":"In the tls.CA Pool Provision, ca.storage.Load failed for one of the ca.PEMKeys storage keys: the PEM-encoded CA certificate could not be read from the configured storage backend (missing key, storage unavailable, permissions). Provision aborts, so the certificate pool cannot be built for this CA module.","triggerScenarios":"ca.storage.Load(ctx, caID) returning an error — the PEM file/blob does not exist in the configured storage, permissions deny reads, or the remote storage backend errored.","commonSituations":"Pointing trusted_ca_certs_pem at paths relative to a different storage root; certificates never uploaded to shared storage in multi-node setups; storage bucket/prefix misconfiguration; file permissions.","solutions":["Verify each configured key exists in the actual storage backend being used (note: with a custom storage block, paths are resolved by that backend, not the local filesystem).","Upload/copy the PEM bundles to the storage keys referenced by the pool.","Check the wrapped error message for the backend-specific cause (not found vs. connection refused vs. permission denied) and fix accordingly."],"exampleFix":"# before\ntrust_pool storage {\n  trusted_ca_certs_pem ca-roots.pem   # not present in storage root\n}\n\n# after\n# ensure the object exists: e.g. file_system storage root /var/lib/caddy\n#   /var/lib/caddy/ca-roots.pem\ntrust_pool storage {\n  trusted_ca_certs_pem ca-roots.pem\n}","handlingStrategy":"validation","validationCode":"// pre-check keys exist in a file_system-backed storage before reload\nimport \"os\"\n\nfunc keysExist(root string, keys []string) error {\n\tfor _, k := range keys {\n\t\tif _, err := os.Stat(filepath.Join(root, k)); err != nil {\n\t\t\treturn fmt.Errorf(\"missing storage key %s: %w\", k, err)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"// reload pipeline: fail the deploy on load errors instead of leaving config half-applied\nif err := applyConfig(newCfg); err != nil {\n\tlog.Printf(\"config apply failed (keeping previous config): %v\", err)\n\treturn err\n}","preventionTips":["Upload certificate bundles to storage before the config referencing them is applied.","Use absolute, backend-relative keys deliberately; remember the custom storage block changes what paths mean.","In multi-node setups, verify the bundle exists in the shared backend from every node."],"tags":["caddy","caddytls","storage","missing-file","io"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","contentChangedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}