Billionmail/BillionMail · error

port must be between 1-65535

Error message

port must be between 1-65535

What it means

validateConfigValue parses port-type config keys (SMTP_PORT, IMAP_PORT, HTTP_PORT, etc., and their lowercase aliases) with public.ParseInt and requires the result to be in 1-65535. Ports outside that range cannot be bound by the mail services, so the value is rejected before being saved.

Source

Thrown at core/internal/controller/settings/settings.go:216

		}

	case "ADMIN_PASSWORD", "admin_password":
		if len(value) < 4 {
			return fmt.Errorf("password length must be at least 4 characters")
		}

	case "BILLIONMAIL_HOSTNAME", "billionmail_hostname":
		// Hostname: allowed letters, numbers, dots, hyphens
		if !public.IsValidHostname(value) {
			return fmt.Errorf("hostname format is incorrect")
		}

	case "SMTP_PORT", "SMTPS_PORT", "SUBMISSION_PORT", "IMAP_PORT", "IMAPS_PORT", "POP_PORT", "POPS_PORT", "HTTP_PORT", "HTTPS_PORT", "REDIS_PORT",
		"smtp", "smtps", "submission", "imap", "imaps", "pop", "pops", "http", "https", "redis_port":
		// Port: 1-65535
		port := public.ParseInt(value)
		if port < 1 || port > 65535 {
			return fmt.Errorf("port must be between 1-65535")
		}

	case "IPV4_NETWORK", "ipv4_network":
		// IPv4 network: CIDR format
		if !public.IsValidCIDR(value) {
			return fmt.Errorf("IPv4 network format is incorrect, please use CIDR format (e.g. 192.168.1.0/24)")
		}

	case "TZ", "timezone":
		// Timezone: check if it is a valid timezone
		if !public.IsValidTimezone(value) {
			return fmt.Errorf("invalid timezone")
		}

	case "FAIL2BAN_INIT", "fail2ban":
		// fail2ban: only allowed y/n or 1/0
		if value != "y" && value != "n" && value != "1" && value != "0" {
			return fmt.Errorf("fail2ban value can only be y/n or 1/0")

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Set the port to an integer between 1 and 65535 (e.g. 25, 465, 587, 993)
  2. Check for accidental concatenation of the port with other text before sending
  3. Ensure the value is a plain decimal string with no units or spaces
  4. If the service should be disabled, use the service's enable/disable flag instead of port 0

Example fix

// before
SMTP_PORT = 0
// after
SMTP_PORT = 25
Defensive patterns

Strategy: validation

Validate before calling

const p = Number(port);
if (!Number.isInteger(p) || p < 1 || p > 65535) throw new Error('port must be between 1-65535');

Type guard

function isValidPort(v: unknown): v is number {
  return typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 65535;
}

Try / catch

try {
  await api.setSystemConfigKey('SMTP_PORT', String(port));
} catch (e) {
  if (String(e.message).includes('port must be between')) {
    notify('Enter a TCP port from 1 to 65535');
  } else throw e;
}

Prevention

When it happens

Trigger: Setting any port key (e.g. SMTP_PORT) to 0, a negative number, a number above 65535, or a non-numeric string that ParseInt maps to an out-of-range value.

Common situations: Copy-paste errors including the plus sign or service name ('SMTP 25'), typos like 655360, empty or blank strings, and attempts to disable a service by setting its port to 0.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/f1da3ae7d1ea76b5. Report an issue: GitHub.