slackhq/nebula · error

invalid mask

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.

Solutions

  1. Change the mask value to a valid CIDR prefix, e.g. mask: 10.0.0.0/8 instead of a dotted netmask
  2. Verify the prefix length is in range (0-32 for IPv4, 0-128 for IPv6)
  3. Check the config value is not quoted or padded with stray whitespace/characters
  4. 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

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


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/0b094c580f338294. Report an issue: GitHub.

Appendix: 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)