sipeed/picoclaw · warning
port %d is out of range (1-65535)
Error message
port %d is out of range (1-65535)
What it means
Validation error (400) from PUT /api/system/launcher-config: launcherconfig.Validate (launcherconfig/config.go:52-54) rejected cfg.Port because it is below 1 or above 65535. The handler copies payload.Port verbatim, and Go zero-fills omitted fields - so omitting "port" yields 0 and this exact message ('port 0 is out of range (1-65535)'). The endpoint is a full replace, not a patch: every PUT must carry a valid port.
Source
Thrown at web/backend/api/launcher_config.go:92
http.Error(w, fmt.Sprintf("Invalid JSON: %v", err), http.StatusBadRequest)
return
}
cfg, err := h.loadLauncherConfig()
if err != nil {
http.Error(w, fmt.Sprintf("Failed to load launcher config: %v", err), http.StatusInternalServerError)
return
}
cfg.Port = payload.Port
cfg.Public = payload.Public
cfg.AllowedCIDRs = append([]string(nil), payload.AllowedCIDRs...)
if payload.AllowLocalhostBypass != nil {
cfg.AllowLocalhostBypass = *payload.AllowLocalhostBypass
}
cfg.TrustedProxyCIDRs = append([]string(nil), payload.TrustedProxyCIDRs...)
cfg.LegacyLauncherToken = ""
if err := launcherconfig.Validate(cfg); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if err := launcherconfig.Save(h.launcherConfigPath(), cfg); err != nil {
http.Error(w, fmt.Sprintf("Failed to save launcher config: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(launcherConfigPayload{
Port: cfg.Port,
Public: cfg.Public,
AllowedCIDRs: append([]string(nil), cfg.AllowedCIDRs...),
AllowLocalhostBypass: cfg.AllowLocalhostBypass,
TrustedProxyCIDRs: append([]string(nil), cfg.TrustedProxyCIDRs...),
})
}
View on GitHub (pinned to 49183d7e8d)
Solutions
- Always include an integer port in 1-65535 in every PUT payload (e.g. 18800, the launcher default)
- If the intent was 'keep current port', first GET /api/system/launcher-config and echo the returned port back in the PUT
- Validate the range client-side before sending
Example fix
// before - port omitted, Go decodes 0, server rejects
PUT /api/system/launcher-config
{"public": true}
// after - full payload with valid port
PUT /api/system/launcher-config
{"port": 18800, "public": true, "allowed_cidrs": ["127.0.0.0/8"], "allow_localhost_bypass": true, "trusted_proxy_cidrs": []} Defensive patterns
Strategy: validation
Validate before calling
if (!Number.isInteger(payload.port) || payload.port < 1 || payload.port > 65535) {
throw new Error(`port ${payload.port} is out of range (1-65535)`);
} Type guard
function hasValidPort(v: unknown): v is {port: number} {
return typeof v === 'object' && v !== null &&
Number.isInteger((v as {port?: unknown}).port) &&
(v as {port: number}).port >= 1 && (v as {port: number}).port <= 65535;
} Try / catch
const res = await fetch('/api/system/launcher-config', {method: 'PUT', ...});
if (res.status === 400) {
const text = await res.text();
if (text.includes('out of range (1-65535)')) {
const cur = await (await fetch('/api/system/launcher-config')).json();
payload.port = cur.port; // echo back the current valid port
return fetch('/api/system/launcher-config', {method: 'PUT', ...}); // retry with corrected payload
}
throw new Error(text);
} Prevention
- The PUT is a full replace: always include a valid integer port, never omit it
- Prefer 1024-49151 registered range or the default 18800 for the launcher
- Populate forms from GET first so the current port rides along in every save
When it happens
Trigger: Omitting port from the payload (defaults to 0); explicitly sending 0 or null; sending 65536+ after a mental math slip; copying a port from another config that uses 0 to mean 'ephemeral'.
Common situations: Clients modeled after PATCH semantics that only send changed fields; UI forms where the port input is left blank and serialized as 0.
Related errors
- Invalid JSON: %v
- build request: %w
- Failed to load launcher config: %v
- invalid CIDR %q
- invalid trusted proxy CIDR %q
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/905c48471a1a7777.
Report an issue: GitHub.