{"record":{"id":"f10b94c983e19f2f","repo":"caddyserver/caddy","slug":"reading-default-caddyfile-v","errorCode":null,"errorMessage":"reading default Caddyfile: %v","messagePattern":"reading default Caddyfile: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/main.go","lineNumber":187,"sourceCode":"\t\t} else {\n\t\t\tconfig, err = os.ReadFile(configFile)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, \"\", \"\", fmt.Errorf(\"reading config from file: %v\", err)\n\t\t\t}\n\t\t\tlogger.Info(\"using config from file\", zap.String(\"file\", configFile))\n\t\t}\n\t} else if adapterName == \"\" {\n\t\t// if the Caddyfile adapter is plugged in, we can try using an\n\t\t// adjacent Caddyfile by default\n\t\tcfgAdapter = caddyconfig.GetAdapter(\"caddyfile\")\n\t\tif cfgAdapter != nil {\n\t\t\tconfig, err = os.ReadFile(\"Caddyfile\")\n\t\t\tif errors.Is(err, fs.ErrNotExist) {\n\t\t\t\t// okay, no default Caddyfile; pretend like this never happened\n\t\t\t\tcfgAdapter = nil\n\t\t\t} else if err != nil {\n\t\t\t\t// default Caddyfile exists, but error reading it\n\t\t\t\treturn nil, \"\", \"\", fmt.Errorf(\"reading default Caddyfile: %v\", err)\n\t\t\t} else {\n\t\t\t\t// success reading default Caddyfile\n\t\t\t\tconfigFile = \"Caddyfile\"\n\t\t\t\tlogger.Info(\"using adjacent Caddyfile\")\n\t\t\t}\n\t\t}\n\t}\n\n\tif yes, err := isCaddyfile(configFile, adapterName); yes {\n\t\tadapterName = \"caddyfile\"\n\t} else if err != nil {\n\t\treturn nil, \"\", \"\", err\n\t}\n\n\t// load config adapter\n\tif adapterName != \"\" {\n\t\tcfgAdapter = caddyconfig.GetAdapter(adapterName)\n\t\tif cfgAdapter == nil {","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/cmd/main.go#L169-L205","documentation":"When no --config is given, Caddy tries the adjacent ./Caddyfile; here that file exists (stat succeeded) but reading it failed with an error other than NotExist — typically EACCES. The distinction matters: a missing default file is silently skipped, an unreadable one is a hard error.","triggerScenarios":"A Caddyfile in the current directory with mode 0600 owned by another user; directory traversal denied; NFS/fuse mounts returning EIO on read.","commonSituations":"Running the CLI as root while the file is fine, but as a less-privileged user it fails; containers where the Caddyfile is mounted with restrictive ownership.","solutions":["chmod/chown the Caddyfile so the CLI user can read it","Or pass --config explicitly with a readable path","Verify: sudo -u <caddy-user> head -1 ./Caddyfile"],"exampleFix":"# before (file owned by root, mode 600, CLI run as caddy user)\ncaddy run\n\n# after\nchmod 644 ./Caddyfile && caddy run","handlingStrategy":"validation","validationCode":"# Ensure the default Caddyfile is readable by the CLI user when present:\n[ -f Caddyfile ] && [ ! -r Caddyfile ] && { echo \"Caddyfile not readable\" >&2; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["chmod 644 Caddyfile (or chown to the caddy user)","Pass --config explicitly to avoid default-file surprises"],"tags":["cli","configuration","permissions","filesystem"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}