slackhq/nebula · error
invalid mask: %s
Error message
invalid mask: %s
What it means
This error is returned by newCalculatedRemotesEntryFromConfig when the 'mask' value in a calculated_remotes config entry cannot be parsed as an IP prefix. Nebula requires the mask to be a valid CIDR prefix (e.g. 10.0.0.0/8) so it can compute calculated remote hosts by masking target IPs. Parse failures of the string with netip.ParsePrefix produce this message carrying the raw offending value.
Source
Thrown at calculated_remote.go:142
}
func newCalculatedRemotesEntryFromConfig(cidr netip.Prefix, raw any) (*calculatedRemote, error) {
rawMap, ok := raw.(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid type: %T", raw)
}
rawValue := rawMap["mask"]
if rawValue == nil {
return nil, fmt.Errorf("missing mask: %v", rawMap)
}
rawMask, ok := rawValue.(string)
if !ok {
return nil, fmt.Errorf("invalid mask (type %T): %v", rawValue, rawValue)
}
maskCidr, err := netip.ParsePrefix(rawMask)
if err != nil {
return nil, fmt.Errorf("invalid mask: %s", rawMask)
}
var port int
rawValue = rawMap["port"]
if rawValue == nil {
return nil, fmt.Errorf("missing port: %v", rawMap)
}
switch v := rawValue.(type) {
case int:
port = v
case string:
port, err = strconv.Atoi(v)
if err != nil {
return nil, fmt.Errorf("invalid port: %s: %w", v, err)
}
default:
return nil, fmt.Errorf("invalid port (type %T): %v", rawValue, rawValue)
}View on GitHub (pinned to dd8f660c0a)
Solutions
- Change the mask value to a valid CIDR prefix, e.g. mask: 10.0.0.0/8 instead of a dotted netmask
- Verify the prefix length is in range (0-32 for IPv4, 0-128 for IPv6)
- Check the config value is not quoted or padded with stray whitespace/characters
- Validate locally with `netip.ParsePrefix` or an online CIDR checker before deploying
Example fix
// before
calculated_remotes:
- mask: 255.255.0.0
port: 4242
// after
calculated_remotes:
- mask: 10.0.0.0/16
port: 4242 Defensive patterns
Strategy: validation
Validate before calling
func validMask(v string) bool {
_, err := netip.ParsePrefix(strings.TrimSpace(v))
return err == nil
}
// before launching nebula: ensure every calculated_remotes mask passes validMask Type guard
func asMaskString(raw any) (string, bool) {
s, ok := raw.(string)
if !ok || !validMask(s) {
return "", false
}
return s, true
} Try / catch
if err != nil {
var cfgErr *ConfigError
if errors.As(err, &cfgErr) {
log.Fatalf("calculated_remotes mask invalid: %v", err)
}
return err
} Prevention
- Always write masks in CIDR notation (10.0.0.0/8), never dotted netmask form
- Lint the Nebula YAML with a schema validator before deploying
- Test config parsing with nebula -config ... -test in CI
- Keep mask values unquoted plain strings to avoid stray whitespace
When it happens
Trigger: Calling newCalculatedRemotesListFromConfig with a config map whose calculated_remotes entry has a 'mask' key set to a string that is not a valid CIDR prefix, e.g. mask: 255.255.0.0 or mask: 10.0.0.0/33 or mask: not-a-mask.
Common situations: Users copying subnet masks from netmask notation (255.255.255.0) instead of CIDR (/24), typos in the prefix length, or omitting the /prefix part entirely when writing the Nebula YAML config.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- config `%s` has invalid CIDR: %s. %w
- missing port: %v
- no outside connection
- no inside interface (tun)
- config `%s` has invalid type: %T
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/0b094c580f338294.
Report an issue: GitHub.