From 34aced3526cffdf344401d2cdd53fdd9fcadb389 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Sun, 21 Dec 2025 22:17:47 -0800 Subject: [PATCH] fix: accurate error messages for explicitly specified unavailable ports When a port is explicitly specified via CLI flags but is unavailable, the error message now correctly reports the originally requested port instead of reporting a fallback port that was calculated internally. The issue was that the config file applied after CLI flag parsing caused isFlagPassed() to return true for ports loaded from the config file (since flag.Visit() was called during config file application), incorrectly marking them as explicitly specified. Solution: Capture which port flags were explicitly passed on the CLI BEFORE the config file is applied, storing them in the explicitPortFlags map. This preserves the accurate distinction between user-specified ports and defaults/config-file ports. Example: - User runs: weed mini -dir=. -s3.port=22 - Now correctly shows: 'port 22 for S3 (specified by flag s3.port) is not available' - Previously incorrectly showed: 'port 8334 for S3...' (some calculated fallback) --- weed/command/mini.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/weed/command/mini.go b/weed/command/mini.go index 6d882cdb2..952ff0c54 100644 --- a/weed/command/mini.go +++ b/weed/command/mini.go @@ -55,6 +55,8 @@ var ( miniWebDavOptions WebDavOption miniAdminOptions AdminOptions createdInitialIAM bool // Track if initial IAM config was created from env vars + // Track which port flags were explicitly passed on CLI before config file is applied + explicitPortFlags map[string]bool ) func init() { @@ -387,8 +389,8 @@ func ensurePortAvailableOnIP(portPtr *int, serviceName string, ip string, reserv original := *portPtr - // Check if this port was explicitly specified by the user - isExplicitPort := isFlagPassed(flagName) + // Check if this port was explicitly specified by the user (from CLI, before config file was applied) + isExplicitPort := explicitPortFlags[flagName] // Skip if this port is reserved for gRPC calculation if reservedPorts[original] { @@ -408,9 +410,11 @@ func ensurePortAvailableOnIP(portPtr *int, serviceName string, ip string, reserv // Check on both the specific IP and on all interfaces (0.0.0.0) for maximum reliability if !isPortOpenOnIP(ip, original) || !isPortAvailable(original) { + // If explicitly specified, fail immediately with the originally requested port if isExplicitPort { return fmt.Errorf("port %d for %s (specified by flag %s) is not available on %s and cannot be used", original, serviceName, flagName, ip) } + // For default ports, try to find an alternative glog.Warningf("Port %d for %s is not available on %s, finding alternative port...", original, serviceName, ip) newPort := findAvailablePortOnIP(ip, original+1, 100, reservedPorts) if newPort == 0 { @@ -666,6 +670,14 @@ func saveMiniConfiguration(dataFolder string) error { func runMini(cmd *Command, args []string) bool { + // Capture which port flags were explicitly passed on CLI BEFORE config file is applied + // This is necessary to distinguish user-specified ports from defaults or config file options + explicitPortFlags = make(map[string]bool) + portFlagNames := []string{"master.port", "filer.port", "volume.port", "s3.port", "webdav.port", "admin.port"} + for _, flagName := range portFlagNames { + explicitPortFlags[flagName] = isFlagPassed(flagName) + } + // Load configuration from file if it exists configOptions, err := loadMiniConfigurationFile(*miniDataFolders) if err != nil {