{"record":{"id":"fcad007518546d40","repo":"caddyserver/caddy","slug":"starting-caddy-administration-endpoint-v","errorCode":null,"errorMessage":"starting caddy administration endpoint: %v","messagePattern":"starting caddy administration endpoint: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"caddy.go","lineNumber":568,"sourceCode":"\t\t\tnewCfg.storage = stor\n\t\t}\n\n\t\tif newCfg.storage == nil {\n\t\t\tnewCfg.storage = DefaultStorage\n\t\t}\n\t\tcertmagic.Default.Storage = newCfg.storage\n\n\t\treturn nil\n\t}()\n\tif err != nil {\n\t\treturn ctx, err\n\t}\n\n\t// start the admin endpoint (and stop any prior one)\n\tif replaceAdminServer {\n\t\terr = replaceLocalAdminServer(newCfg, ctx)\n\t\tif err != nil {\n\t\t\treturn ctx, fmt.Errorf(\"starting caddy administration endpoint: %v\", err)\n\t\t}\n\t}\n\n\t// Load and Provision each app and their submodules\n\terr = func() error {\n\t\tfor appName := range newCfg.AppsRaw {\n\t\t\tif _, err := ctx.App(appName); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}()\n\treturn ctx, err\n}\n\n// ProvisionContext creates a new context from the configuration and provisions storage\n// and app modules.\n// The function is intended for testing and advanced use cases only, typically `Run` should be","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddy.go#L550-L586","documentation":"When a config change alters admin endpoint settings, run() calls replaceLocalAdminServer to tear down the old admin listener and bind the new one. Any failure — the new address cannot be parsed/bound, port in use, permission denied — is wrapped as 'starting caddy administration endpoint'. Because this happens inside the load, the whole config change fails and the old state is restored.","triggerScenarios":"Loading a config whose admin.listen changes to an address already bound by another process or the current admin server in a way that can't be transitioned; binding a privileged port without capability; unix socket path whose directory does not exist; remote admin ('remote_admin') TLS material being invalid.","commonSituations":"Repointing admin to a unix socket with a missing /run/caddy directory; another service squatting on the target port; SELinux denying the socket bind; changing admin origin/host to an interface Caddy cannot bind.","solutions":["Check the wrapped error — it names the bind failure and address.","Free the target port or pick another one; for unix sockets, mkdir -p the parent dir and check permissions.","For privileged ports grant cap_net_bind_service or run from systemd with the capability.","Keep the admin address stable across config loads unless a change is really needed."],"exampleFix":"// before\n\"admin\": { \"listen\": \"unix//run/caddy/admin.sock\" }  // /run/caddy missing\n\n// after (ensure dir exists)\nmkdir -p /run/caddy && chown caddy /run/caddy  # then reload","handlingStrategy":"validation","validationCode":"// Pre-flight the admin bind before loading a config that changes it.\nif cfg.Admin.Listen != \"\" {\n    na, err := caddy.ParseNetworkAddress(cfg.Admin.Listen)\n    if err != nil || na.PortRangeSize() != 1 { return errors.New(\"bad admin address\") }\n    ln, err := net.Listen(na.Network, na.JoinHostPort(0, 0))\n    if err != nil { return fmt.Errorf(\"admin bind would fail: %w\", err) }\n    ln.Close()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid changing admin.listen in routine config pushes; pin it once.","Create unix socket directories with correct ownership before deploy.","Check port occupancy and capabilities before switching admin ports."],"tags":["caddy","admin-api","bind","startup","config"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}