{"record":{"id":"a4d99e64881f1f47","repo":"caddyserver/caddy","slug":"no-identifiers-configured","errorCode":null,"errorMessage":"no identifiers configured","messagePattern":"no identifiers configured","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"admin.go","lineNumber":655,"sourceCode":"\t\t\tGetConfigForCert: func(certmagic.Certificate) (*certmagic.Config, error) {\n\t\t\t\treturn cmCfg, nil\n\t\t\t},\n\t\t\tLogger: logger.Named(\"cache\"),\n\t\t})\n\t}\n\tcmCfg = certmagic.New(identityCertCache, template)\n\treturn cmCfg\n}\n\n// IdentityCredentials returns this instance's configured, managed identity credentials\n// that can be used in TLS client authentication.\nfunc (ctx Context) IdentityCredentials(logger *zap.Logger) ([]tls.Certificate, error) {\n\tif ctx.cfg == nil || ctx.cfg.Admin == nil || ctx.cfg.Admin.Identity == nil {\n\t\treturn nil, fmt.Errorf(\"no server identity configured\")\n\t}\n\tident := ctx.cfg.Admin.Identity\n\tif len(ident.Identifiers) == 0 {\n\t\treturn nil, fmt.Errorf(\"no identifiers configured\")\n\t}\n\tif logger == nil {\n\t\tlogger = Log()\n\t}\n\tmagic := ident.certmagicConfig(logger, false)\n\treturn magic.ClientCredentials(ctx, ident.Identifiers)\n}\n\n// enforceAccessControls enforces application-layer access controls for r based on remote.\n// It expects that the TLS server has already established at least one verified chain of\n// trust, and then looks for a matching, authorized public key that is allowed to access\n// the defined path(s) using the defined method(s).\nfunc (remote RemoteAdmin) enforceAccessControls(r *http.Request) error {\n\tfor _, chain := range r.TLS.VerifiedChains {\n\t\tfor _, peerCert := range chain {\n\t\t\tfor _, adminAccess := range remote.AccessControl {\n\t\t\t\tfor _, allowedKey := range adminAccess.publicKeys {\n\t\t\t\t\t// see if we found a matching public key; the TLS server already verified the chain","sourceCodeStart":637,"sourceCodeEnd":673,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/admin.go#L637-L673","documentation":"IdentityCredentials rejects an admin.identity section that exists but has an empty identifiers list. Identifiers (SANs) are required because certmagic must know which names to obtain credentials for; without them, magic.ClientCredentials cannot request any certificate.","triggerScenarios":"admin.identity: {} present in JSON with no 'identifiers' array, or an empty array; config templates that scaffold identity but never fill in names.","commonSituations":"Copied identity examples with placeholders removed; automation that emits the identity object conditionally and leaves identifiers unset.","solutions":["Add at least one identifier: \"identifiers\": [\"host.example.com\"] matching the name peers will verify","Ensure the identifiers array is not empty after templating/rendering","Validate the config with caddy validate before deploying"],"exampleFix":"// before\n\"identity\": { \"issuers\": [{\"module\": \"internal\"}] }\n\n// after\n\"identity\": {\n  \"identifiers\": [\"caddy-node1.internal\"],\n  \"issuers\": [{\"module\": \"internal\"}]\n}","handlingStrategy":"validation","validationCode":"func identityHasIdentifiers(cfg *Config) bool {\n\treturn cfg != nil && cfg.Admin != nil && cfg.Admin.Identity != nil &&\n\t\tlen(cfg.Admin.Identity.Identifiers) > 0\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always populate identifiers when adding an identity block","Assert non-empty identifiers in config-rendering tests","Run caddy validate after templating configs"],"tags":["admin-api","identity","configuration","validation"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}