{"record":{"id":"9450310e5fbad376","repo":"slackhq/nebula","slug":"missing-mask-v","errorCode":null,"errorMessage":"missing mask: %v","messagePattern":"missing mask: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"calculated_remote.go","lineNumber":134,"sourceCode":"\t\tc, err := newCalculatedRemotesEntryFromConfig(cidr, e)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"calculated_remotes entry: %w\", err)\n\t\t}\n\t\tl = append(l, c)\n\t}\n\n\treturn l, nil\n}\n\nfunc newCalculatedRemotesEntryFromConfig(cidr netip.Prefix, raw any) (*calculatedRemote, error) {\n\trawMap, ok := raw.(map[string]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid type: %T\", raw)\n\t}\n\n\trawValue := rawMap[\"mask\"]\n\tif rawValue == nil {\n\t\treturn nil, fmt.Errorf(\"missing mask: %v\", rawMap)\n\t}\n\trawMask, ok := rawValue.(string)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid mask (type %T): %v\", rawValue, rawValue)\n\t}\n\tmaskCidr, err := netip.ParsePrefix(rawMask)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid mask: %s\", rawMask)\n\t}\n\n\tvar port int\n\trawValue = rawMap[\"port\"]\n\tif rawValue == nil {\n\t\treturn nil, fmt.Errorf(\"missing port: %v\", rawMap)\n\t}\n\tswitch v := rawValue.(type) {\n\tcase int:\n\t\tport = v","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/calculated_remote.go#L116-L152","documentation":"Every calculated_remotes entry must include a `mask` key; newCalculatedRemotesEntryFromConfig throws this when rawMap[\"mask\"] is absent or explicitly null. Without a mask the library cannot compute the calculated remote address and prints the whole entry map to help locate the offender.","triggerScenarios":"A calculated_remotes entry map lacks the `mask` key entirely, or has `mask:` with no value (YAML null), causing rawValue == nil.","commonSituations":"Typos like `masks:` or `Mask:` (key lookup is exact and case-sensitive), deleted lines during config edits, or templates that skip optional fields.","solutions":["Add a `mask: <cidr>` key with a valid CIDR string to the entry","Check for key typos or case mismatches (`mask` must be lowercase and exact)","Ensure YAML doesn't parse the mask value as empty/null (provide a value after the colon)"],"exampleFix":"// before\n- port: 4242\n// after\n- mask: 10.0.0.0/8\n  port: 4242","handlingStrategy":"validation","validationCode":"for _, e := range list {\n\tif m, ok := e.(map[string]any); ok {\n\t\tif _, present := m[\"mask\"]; !present || m[\"mask\"] == nil {\n\t\t\treturn fmt.Errorf(\"entry missing mask: %v\", m)\n\t\t}\n\t}\n}","typeGuard":"func hasMask(e map[string]any) bool {\n\tv, ok := e[\"mask\"]\n\treturn ok && v != nil\n}","tryCatchPattern":"if err != nil {\n\tif strings.Contains(err.Error(), \"missing mask\") {\n\t\t// message prints the whole offending entry map; locate and fix the entry\n\t\treturn fmt.Errorf(\"add mask key to entry: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Spell the key exactly `mask` (lowercase) — lookup is case-sensitive","Never leave `mask:` with an empty value in YAML","Validate required keys (mask, port) with a schema before deployment"],"tags":["nebula","config","missing-field","calculated-remotes"],"backgroundTag":"missing-required-argument","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}