caddyserver/caddy · error
reading config from file: %v
Error message
reading config from file: %v
What it means
os.ReadFile on the explicitly given --config file failed, wrapped as 'reading config from file'. The underlying error is almost always 'no such file or directory' or 'permission denied' for that exact path.
Source
Thrown at cmd/main.go:172
if adapterName != "" && configFile == "" {
return nil, "", "", fmt.Errorf("cannot adapt config without config file (use --config)")
}
// load initial config and adapter
var config []byte
var cfgAdapter caddyconfig.Adapter
var err error
if configFile != "" {
if configFile == "-" {
config, err = io.ReadAll(os.Stdin)
if err != nil {
return nil, "", "", fmt.Errorf("reading config from stdin: %v", err)
}
logger.Info("using config from stdin")
} else {
config, err = os.ReadFile(configFile)
if err != nil {
return nil, "", "", fmt.Errorf("reading config from file: %v", err)
}
logger.Info("using config from file", zap.String("file", configFile))
}
} else if adapterName == "" {
// if the Caddyfile adapter is plugged in, we can try using an
// adjacent Caddyfile by default
cfgAdapter = caddyconfig.GetAdapter("caddyfile")
if cfgAdapter != nil {
config, err = os.ReadFile("Caddyfile")
if errors.Is(err, fs.ErrNotExist) {
// okay, no default Caddyfile; pretend like this never happened
cfgAdapter = nil
} else if err != nil {
// default Caddyfile exists, but error reading it
return nil, "", "", fmt.Errorf("reading default Caddyfile: %v", err)
} else {
// success reading default Caddyfile
configFile = "Caddyfile"View on GitHub (pinned to 50e54ee279)
Solutions
- Verify the path: ls -l <config> from the same user and working directory
- Use an absolute path in --config, especially in service units
- Fix read permissions on the file (and execute permission on parent dirs)
Example fix
# before ExecStart=/usr/bin/caddy run --config Caddyfile # after ExecStart=/usr/bin/caddy run --config /etc/caddy/Caddyfile
Defensive patterns
Strategy: validation
Validate before calling
# Resolve and stat the config before invoking caddy:
CONFIG=$(realpath "$CONFIG")
[ -r "$CONFIG" ] || { echo "cannot read $CONFIG" >&2; exit 1; } Prevention
- Use absolute paths in service units and cron jobs
- Check readability as the same user that runs caddy
When it happens
Trigger: Typo'd or wrong-case path in --config; file exists but the running user lacks read permission; relative path interpreted against an unexpected working directory (systemd, cron).
Common situations: Service units with WorkingDirectory! set so a relative --config resolves wrong; permissions tightened on /etc/caddy; configs generated to a temp path that was cleaned up.
Related errors
- no config file to load; either use --config flag or ensure C
- reading default Caddyfile: %v
- reading environment file: %v
- invalid admin address %s: %v
- caddy responded with error: HTTP %d: %s
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/961cdc3d608e710c.
Report an issue: GitHub.