sipeed/picoclaw · critical
must be in range 1-65535
Error message
must be in range 1-65535
What it means
Startup-time port validation in web/backend/main.go. effectivePort (from flag, env, or config resolution) is parsed with strconv.Atoi and range-checked; an out-of-range integer produces this error, a non-integer surfaces the Atoi error, and either way logger.Fatalf terminates the process before listeners open. This is deliberate fail-fast: the launcher refuses to run on an unusable port.
Source
Thrown at web/backend/main.go:564
}
if hostOverrideActive && explicitPublic {
logger.InfoC("web", "Ignoring -public because launcher host was explicitly set")
}
if decision := launcherAllowlistBypassLogPolicy(hostInput, effectivePublic, launcherCfg); decision.emit {
switch decision.level {
case logger.WARN:
logger.WarnC("web", decision.message)
default:
logger.InfoC("web", decision.message)
}
}
portNum, err := strconv.Atoi(effectivePort)
if err != nil || portNum < 1 || portNum > 65535 {
if err == nil {
err = errors.New("must be in range 1-65535")
}
logger.Fatalf("Invalid port %q: %v", effectivePort, err)
}
openResult, err := openLauncherListeners(hostInput, effectivePublic, effectivePort)
if err != nil {
logger.Fatalf("Failed to open launcher listener(s): %v", err)
}
listeners := openResult.Listeners
dashboardSessionCookie, dashErr := middleware.NewLauncherDashboardSessionCookie()
if dashErr != nil {
logger.Fatalf("Dashboard auth setup failed: %v", dashErr)
}
// Open the bcrypt password store (creates the DB file on first run).
authStore, authStoreErr := dashboardauth.New(picoHome)
var passwordStore api.PasswordStoreView on GitHub (pinned to 49183d7e8d)
Solutions
- Set a valid port: an integer between 1 and 65535 (unprivileged users need >1024)
- Print the effective value before launching to catch env/flag precedence surprises
- In wrapper scripts, validate with a one-liner before exec: case "$PORT" in ''|*[!0-9]*|0|655[3-6][5-9]*) echo bad port; exit;; esac
- If you meant 'any free port', pick one yourself (net.Listen :0 then close) because this launcher does not accept 0
Example fix
// before
logger.Fatalf("Invalid port %q: %v", effectivePort, err)
// after (validate before startup, in the caller)
portNum, err := strconv.Atoi(portStr)
if err != nil || portNum < 1 || portNum > 65535 {
return fmt.Errorf("port %q must be in range 1-65535", portStr)
} Defensive patterns
Strategy: validation
Validate before calling
func validPort(s string) bool {
n, err := strconv.Atoi(strings.TrimSpace(s))
return err == nil && n >= 1 && n <= 65535
}
if !validPort(os.Getenv("PORT")) {
return fmt.Errorf("PORT must be 1-65535, got %q", os.Getenv("PORT"))
} Prevention
- Validate ports in wrapper scripts/systemd units before exec'ing the binary — it exits via Fatalf
- Note that port 0 ('pick a free port') is rejected here; choose explicitly
- Trim whitespace from env-provided values; strconv.Atoi does not
- Unprivileged users must pick >1024 or the listener open will fail next
When it happens
Trigger: Launching with -port 0, -port 65536, -port 8080t, or an env/config value that resolves to those; whitespace or a trailing newline in a port env var making Atoi fail.
Common situations: Typo'd flag in a systemd unit or Dockerfile; CI overriding PORT with an empty or invalid value; scripts passing a computed port that can exceed 65535 after adding an offset.
Related errors
- failed to load MCP servers: %w
- irc server is required
- irc nick is required
- line channel_secret and channel_access_token are required
- error creating channel manager: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/c8d184ff2937291d.
Report an issue: GitHub.