Repository: caddyserver/caddy (language: go)

Issue:
`caddy validate` does not check if the Caddyfile exists
I think this is pretty self-explanatory:
```
$ caddy adapt
Error: input file required when there is no Caddyfile in current directory (use --config flag)
$ caddy validate
Error: decoding config: unexpected end of JSON input
```

The `validate` command, unlike `adapt` misses check that assesses the file even exists in the first place. With that, the user may assume the file was read and that they have some syntax error they'll be endlessly looking for, even though that's not the problem...

Check for adapt exists here:
https://github.com/caddyserver/caddy/blob/dfe17c33efb1653c0dcbcb8238935e7c72d714dd/cmd/commandfuncs.go#L439-L442

Missing in this func:
https://github.com/caddyserver/caddy/blob/dfe17c33efb1653c0dcbcb8238935e7c72d714dd/cmd/commandfuncs.go#L506

Should be simple fix for someone who already has a dev environment setup to test it out before committing (hence I'm creating an issue and not PR)
`caddy validate` does not check if the Caddyfile exists
I think this is pretty self-explanatory:
```
$ caddy adapt
Error: input file required when there is no Caddyfile in current directory (use --config flag)
$ caddy validate
Error: decoding config: unexpected end of JSON input
```

The `validate` command, unlike `adapt` misses check that assesses the file even exists in the first place. With that, the user may assume the file was read and that they have some syntax error they'll be endlessly looking for, even though that's not the problem...

Check for adapt exists here:
https://github.com/caddyserver/caddy/blob/dfe17c33efb1653c0dcbcb8238935e7c72d714dd/cmd/commandfuncs.go#L439-L442

Missing in this func:
https://github.com/caddyserver/caddy/blob/dfe17c33efb1653c0dcbcb8238935e7c72d714dd/cmd/commandfuncs.go#L506

Should be simple fix for someone who already has a dev environment setup to test it out before committing (hence I'm creating an issue and not PR)


Discussion / hints:
I'm working on this
I'm working on this

Fix patch:
diff --git a/cmd/commandfuncs.go b/cmd/commandfuncs.go
index 837526ed013..f997f069ee1 100644
--- a/cmd/commandfuncs.go
+++ b/cmd/commandfuncs.go
@@ -22,6 +22,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/fs"
 	"log"
 	"net"
 	"net/http"
@@ -423,24 +424,12 @@ func cmdAdaptConfig(fl Flags) (int, error) {
 	adaptCmdPrettyFlag := fl.Bool("pretty")
 	adaptCmdValidateFlag := fl.Bool("validate")
 
-	// if no input file was specified, try a default
-	// Caddyfile if the Caddyfile adapter is plugged in
-	if adaptCmdInputFlag == "" && caddyconfig.GetAdapter("caddyfile") != nil {
-		_, err := os.Stat("Caddyfile")
-		if err == nil {
-			// default Caddyfile exists
-			adaptCmdInputFlag = "Caddyfile"
-			caddy.Log().Info("using adjacent Caddyfile")
-		} else if !os.IsNotExist(err) {
-			// default Caddyfile exists, but error accessing it
-			return caddy.ExitCodeFailedStartup, fmt.Errorf("accessing default Caddyfile: %v", err)
-		}
+	var err error
+	adaptCmdInputFlag, err = configFileWithRespectToDefault(caddy.Log(), adaptCmdInputFlag)
+	if err != nil {
+		return caddy.ExitCodeFailedStartup, err
 	}
 
-	if adaptCmdInputFlag == "" {
-		return caddy.ExitCodeFailedStartup,
-			fmt.Errorf("input file required when there is no Caddyfile in current directory (use --config flag)")
-	}
 	if adaptCmdAdapterFlag == "" {
 		return caddy.ExitCodeFailedStartup,
 			fmt.Errorf("adapter name is required (use --adapt flag or leave unspecified for default)")
@@ -517,6 +506,17 @@ func cmdValidateConfig(fl Flags) (int, error) {
 		}
 	}
 
+	// use default config and ensure a config file is specified
+	var err error
+	validateCmdConfigFlag, err = configFileWithRespectToDefault(caddy.Log(), validateCmdConfigFlag)
+	if err != nil {
+		return caddy.ExitCodeFailedStartup, err
+	}
+	if validateCmdConfigFlag == "" {
+		return caddy.ExitCodeFailedStartup,
+			fmt.Errorf("input file required when there is no Caddyfile in current directory (use --config flag)")
+	}
+
 	input, _, err := LoadConfig(validateCmdConfigFlag, validateCmdAdapterFlag)
 	if err != nil {
 		return caddy.ExitCodeFailedStartup, err
@@ -736,6 +736,31 @@ func DetermineAdminAPIAddress(address string, config []byte, configFile, configA
 	return caddy.DefaultAdminListen, nil
 }
 
+// configFileWithRespectToDefault returns the filename to use for loading the config, based
+// on whether a config file is already specified and a supported default config file exists.
+func configFileWithRespectToDefault(logger *zap.Logger, configFile string) (string, error) {
+	const defaultCaddyfile = "Caddyfile"
+
+	// if no input file was specified, try a default Caddyfile if the Caddyfile adapter is plugged in
+	if configFile == "" && caddyconfig.GetAdapter("caddyfile") != nil {
+		_, err := os.Stat(defaultCaddyfile)
+		if err == nil {
+			// default Caddyfile exists
+			if logger != nil {
+				logger.Info("using adjacent Caddyfile")
+			}
+			return defaultCaddyfile, nil
+		}
+		if !errors.Is(err, fs.ErrNotExist) {
+			// problem checking
+			return configFile, fmt.Errorf("checking if default Caddyfile exists: %v", err)
+		}
+	}
+
+	// default config file does not exist or is irrelevant
+	return configFile, nil
+}
+
 type moduleInfo struct {
 	caddyModuleID string
 	goModule      *debug.Module
diff --git a/cmd/main.go b/cmd/main.go
index bfbd0bbceb1..53b8d675230 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -117,9 +117,8 @@ func loadConfigWithLogger(logger *zap.Logger, configFile, adapterName string) ([
 				zap.String("config_adapter", adapterName))
 		}
 	} else if adapterName == "" {
-		// as a special case when no config file or adapter
-		// is specified, see if the Caddyfile adapter is
-		// plugged in, and if so, try using a default Caddyfile
+		// 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")


Test patch: