Billionmail/BillionMail · error
IPv4 network format is incorrect, please use CIDR format (e.
Error message
IPv4 network format is incorrect, please use CIDR format (e.g. 192.168.1.0/24)
What it means
validateConfigValue validates the IPV4_NETWORK key with public.IsValidCIDR and rejects values that are not valid IPv4 CIDR notation. This network is written into Docker/mail-service network configuration, so a malformed value would break container networking. An example is embedded in the message.
Source
Thrown at core/internal/controller/settings/settings.go:222
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")
}
case "RETENTION_DAYS", "retention_days":
// retention_days: must be a number
if _, err := strconv.Atoi(value); err != nil {
return fmt.Errorf("retention_days must be a number")
}View on GitHub (pinned to fc36c76c05)
Solutions
- Use CIDR format with network address and prefix, e.g. 192.168.1.0/24
- Convert a netmask to a prefix length (255.255.255.0 → /24)
- Validate with a CIDR parser (Go net.ParseCIDR) before calling the API
- Match the existing Docker network subnet if one is already deployed
Example fix
// before IPV4_NETWORK = 192.168.1.0 // after IPV4_NETWORK = 192.168.1.0/24
Defensive patterns
Strategy: validation
Validate before calling
function isValidCIDR(v: string): boolean {
const m = v.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/);
if (!m) return false;
const ok = [1,2,3,4].every(i => +m[i] >= 0 && +m[i] <= 255);
return ok && +m[5] <= 32;
}
if (!isValidCIDR(network)) throw new Error('use CIDR, e.g. 192.168.1.0/24'); Type guard
function isCIDR(v: string): boolean {
return /^\d{1,3}(\.\d{1,3}){3}\/(\d|[12]\d|3[0-2])$/.test(v);
} Try / catch
try {
await api.setSystemConfigKey('IPV4_NETWORK', network);
} catch (e) {
if (String(e.message).includes('CIDR')) {
notify('IPv4 network must be in CIDR format, e.g. 192.168.1.0/24');
} else throw e;
} Prevention
- Always include the /prefix length
- Convert netmasks to prefix lengths before submitting
- Use the network address, not the gateway or broadcast address
- Reuse an existing Docker subnet if one is already provisioned
When it happens
Trigger: Setting IPV4_NETWORK to a bare IP (192.168.1.0), an IPv6 value, a netmask form (255.255.255.0), a range with a hyphen, or an incorrect prefix length (192.168.1.0/33).
Common situations: Users confuse netmask with CIDR prefix, omit the /prefix, or paste the Docker subnet with extra whitespace or a gateway address instead of the network address.
Related errors
- hostname format is incorrect
- port must be between 1-65535
- invalid timezone
- fail2ban value can only be y/n or 1/0
- retention_days must be a number
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/155dbc17e3d2baad.
Report an issue: GitHub.