@@ -252,6 +252,34 @@ Or if you have an existing function:
252252 // configured to build/run the language of the function.
253253 job , err := client .Run (cmd .Context (), f , fn .RunWithAddress (cfg .Address ))
254254 if err != nil {
255+ // Catch port unavailable errors and provide helpful CLI guidance
256+ var portErr * fn.ErrPortUnavailableError
257+ if errors .As (err , & portErr ) {
258+ if portErr .IsPermissionDenied () {
259+ return fmt .Errorf (`cannot choose port
260+
261+ Cannot bind to port %s: permission denied.
262+
263+ Port %s is a privileged port and requires administrator/root permissions.
264+
265+ Try this:
266+ sudo func run --address %s Run with elevated permissions
267+ func run --address 127.0.0.1:8080 Use non-privileged port
268+
269+ For more options, run 'func run --help'` , portErr .Port , portErr .Port , cfg .Address )
270+ }
271+ return fmt .Errorf (`cannot choose port
272+
273+ Port %s is not available.
274+
275+ The port may be in use by another process, or you may not have permission to bind to it.
276+
277+ Try this:
278+ func run --address 127.0.0.1:8080 Use a different port
279+ lsof -i :%s Check if port is in use (Linux/Mac)
280+
281+ For more options, run 'func run --help'` , portErr .Port , portErr .Port )
282+ }
255283 return
256284 }
257285 defer func () {
@@ -388,6 +416,50 @@ func (c runConfig) Validate(cmd *cobra.Command, f fn.Function) (err error) {
388416 }
389417 }
390418
419+ // Validate address port if provided
420+ if c .Address != "" {
421+ host , port , err := net .SplitHostPort (c .Address )
422+ if err != nil {
423+ // Invalid address format will be caught by runner
424+ return nil // Let runner handle address format errors
425+ }
426+
427+ // Warn about port-only addresses (missing host)
428+ if host == "" {
429+ return fmt .Errorf (`invalid address format '%s': address must include both host and port
430+
431+ Address format: host:port
432+
433+ Examples:
434+ 127.0.0.1:8080 Localhost only
435+ 0.0.0.0:8080 All interfaces (IPv4)
436+ [::]:8080 All interfaces (IPv6)
437+
438+ For more options, run 'func run --help'` , c .Address )
439+ }
440+
441+ // Validate port range (1-65535)
442+ portNum , err := strconv .Atoi (port )
443+ if err != nil {
444+ return fmt .Errorf (`invalid port '%s': port must be a number between 1 and 65535
445+
446+ Examples:
447+ func run --address 127.0.0.1:8080
448+ func run --address 0.0.0.0:9090
449+
450+ For more options, run 'func run --help'` , port )
451+ }
452+ if portNum < 1 || portNum > 65535 {
453+ return fmt .Errorf (`invalid port '%d': port must be between 1 and 65535
454+
455+ Examples:
456+ func run --address 127.0.0.1:8080
457+ func run --address 0.0.0.0:9090
458+
459+ For more options, run 'func run --help'` , portNum )
460+ }
461+ }
462+
391463 if f .Build .Builder == "host" && ! oci .IsSupported (f .Runtime ) {
392464 return fmt .Errorf ("the %q runtime currently requires being run in a container" , f .Runtime )
393465 }
0 commit comments