{"record":{"id":"a696d0d13daa23f4","repo":"caddyserver/caddy","slug":"replacing-listen-address-v","errorCode":null,"errorMessage":"replacing listen address: %v","messagePattern":"replacing listen address: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"admin.go","lineNumber":1394,"sourceCode":"type APIError struct {\n\tHTTPStatus int    `json:\"-\"`\n\tErr        error  `json:\"-\"`\n\tMessage    string `json:\"error\"`\n}\n\nfunc (e APIError) Error() string {\n\tif e.Err != nil {\n\t\treturn e.Err.Error()\n\t}\n\treturn e.Message\n}\n\n// parseAdminListenAddr extracts a singular listen address from either addr\n// or defaultAddr, returning the network and the address of the listener.\nfunc parseAdminListenAddr(addr string, defaultAddr string) (NetworkAddress, error) {\n\tinput, err := NewReplacer().ReplaceOrErr(addr, true, true)\n\tif err != nil {\n\t\treturn NetworkAddress{}, fmt.Errorf(\"replacing listen address: %v\", err)\n\t}\n\tif input == \"\" {\n\t\tinput = defaultAddr\n\t}\n\tlistenAddr, err := ParseNetworkAddress(input)\n\tif err != nil {\n\t\treturn NetworkAddress{}, fmt.Errorf(\"parsing listener address: %v\", err)\n\t}\n\tif listenAddr.PortRangeSize() != 1 {\n\t\treturn NetworkAddress{}, fmt.Errorf(\"must be exactly one listener address; cannot listen on: %s\", listenAddr)\n\t}\n\treturn listenAddr, nil\n}\n\n// decodeBase64DERCert base64-decodes, then DER-decodes, certStr.\nfunc decodeBase64DERCert(certStr string) (*x509.Certificate, error) {\n\tderBytes, err := base64.StdEncoding.DecodeString(certStr)\n\tif err != nil {","sourceCodeStart":1376,"sourceCodeEnd":1412,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/admin.go#L1376-L1412","documentation":"parseAdminListenAddr applies Caddy's placeholder replacer (e.g. {$ENV} and {file...} placeholders) to the admin endpoint's listen address before parsing it. ReplaceOrErr is called with error-on-empty and error-on-missing, so any placeholder in the admin address that is unresolvable, unset, or expands to empty aborts startup with 'replacing listen address'. The wrapped %v is the replacer's underlying error naming the offending placeholder.","triggerScenarios":"Setting 'admin {$CADDY_ADMIN}:2020' (or admin_listen/offline addressing via JSON \"admin\":{\"listen\":\"...\"}) where the referenced environment variable or file placeholder does not exist, is empty, or is malformed (e.g. unclosed '{$'). Any admin API config load or 'caddy run' whose Admin.Listen contains an unresolvable placeholder hits this in parseAdminListenAddr.","commonSituations":"Running Caddy under systemd/container where an env var referenced in the admin block is not exported; typos like {$ADMIM_ADDR}; migrating configs between environments where the variable was previously set; using {file./path} where the file is missing.","solutions":["Check the wrapped error text — it names exactly which placeholder failed to resolve.","Export/define the missing environment variable (or create the referenced file) before starting Caddy.","Fix the placeholder spelling/syntax (e.g. {$CADDY_ADMIN} with matching braces) or remove it and hard-code the admin address.","If the variable is legitimately empty in some deployments, provide a default: {$CADDY_ADMIN:localhost:2019}."],"exampleFix":"// Caddyfile - before\nadmin {$CADDY_ADMIN}:2020\n\n// after (inline default so empty/unset never fails)\nadmin {$CADDY_ADMIN:localhost:2019}","handlingStrategy":"validation","validationCode":"// Before loading config, verify every placeholder in admin.listen resolves.\naddr := cfg.Admin.Listen // e.g. \"{$CADDY_ADMIN}:2020\"\nif _, err := caddy.NewReplacer().ReplaceOrErr(addr, true, true); err != nil {\n    log.Fatalf(\"admin listen placeholder will fail: %v\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer inline placeholder defaults in configs: {$VAR:localhost:2019}.","Export all referenced env vars in the unit file/container before ExecStart.","Run 'caddy validate --config' in CI with the same environment as production."],"tags":["caddy","admin-api","config","placeholders","environment"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}