{"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":"A storage-backed trust pool could not Load() one of the configured PEM keys from its storage backend. The wrapped error indicates whether the key was not found, was unreadable, or the backend failed.","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","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}