{"record":{"id":"580bdbbe37d8b042","repo":"netbirdio/netbird","slug":"parse-source-range-w","errorCode":null,"errorMessage":"parse source range: %w","messagePattern":"parse source range: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/internal/acl/manager.go","lineNumber":248,"sourceCode":"\t\t\t}\n\t\t\t// implicitly deleted from the map\n\t\t}\n\t}\n\n\td.routeRules = newRouteRules\n\treturn nberrors.FormatErrorOrNil(merr)\n}\n\nfunc (d *DefaultManager) applyRouteACL(rule *mgmProto.RouteFirewallRule, dynamicResolver bool) (id.RuleID, error) {\n\tif len(rule.SourceRanges) == 0 {\n\t\treturn \"\", ErrSourceRangesEmpty\n\t}\n\n\tvar sources []netip.Prefix\n\tfor _, sourceRange := range rule.SourceRanges {\n\t\tsource, err := netip.ParsePrefix(sourceRange)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"parse source range: %w\", err)\n\t\t}\n\t\tsources = append(sources, source)\n\t}\n\n\tdestination, err := determineDestination(rule, dynamicResolver, sources)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"determine destination: %w\", err)\n\t}\n\n\tprotocol, err := convertToFirewallProtocol(rule.Protocol)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid protocol: %w\", err)\n\t}\n\n\taction, err := convertFirewallAction(rule.Action)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid action: %w\", err)\n\t}","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/internal/acl/manager.go#L230-L266","documentation":"Returned by applyRouteACL when netip.ParsePrefix rejects one of the rule's SourceRanges strings from the management proto (RouteFirewallRule.SourceRanges). ParsePrefix requires a strict `addr/bits` CIDR (netip is stricter than older net utils: no spaces, no bare IPs, bits must be valid for the family, no zone qualifiers). The error aborts that single rule before destination/protocol are even examined.","triggerScenarios":"Management sending a source range as a bare IP (`10.0.0.5` without `/32`), a malformed mask (`10.0.0.0/33`), a hostname, or a v4-in-v6 mix; typical when policies are authored through the REST API rather than the dashboard, or by a management version that skips validation.","commonSituations":"API/script-driven policy creation without CIDR validation; copy-paste of IP lists into source ranges; older self-hosted management builds.","solutions":["Fix the source range in the policy to a valid CIDR - bare IPs must be written as a.b.c.d/32 (or /128 for v6)","Validate before saving via API: `if _, err := netip.ParsePrefix(r); err != nil { ... }`","After fixing, force a network map update (reconnect the peer or edit the policy) so the agent retries the rule"],"exampleFix":"// before (policy payload)\n{\"source_ranges\": [\"10.20.0.5\"]}\n\n// after\n{\"source_ranges\": [\"10.20.0.5/32\"]}\n\n// api-side guard\nfunc validSourceRanges(rs []string) bool {\n    for _, r := range rs {\n        if _, err := netip.ParsePrefix(r); err != nil {\n            return false\n        }\n    }\n    return true\n}","handlingStrategy":"validation","validationCode":"// run on every source range before creating/updating a policy\nfunc parseSourceRanges(ranges []string) ([]netip.Prefix, error) {\n    out := make([]netip.Prefix, 0, len(ranges))\n    for _, r := range ranges {\n        p, err := netip.ParsePrefix(strings.TrimSpace(r))\n        if err != nil {\n            return nil, fmt.Errorf(\"source range %q: %w\", r, err)\n        }\n        out = append(out, p)\n    }\n    return out, nil\n}","typeGuard":"func isStrictCIDR(s string) bool {\n    _, err := netip.ParsePrefix(s)\n    return err == nil\n}","tryCatchPattern":"if _, err := netip.ParsePrefix(sourceRange); err != nil {\n    log.Warnf(\"skipping malformed source range %q, management data issue: %v\", sourceRange, err)\n    continue // skip one range, keep the rest of the rule working where possible\n}","preventionTips":["Always write CIDRs with explicit prefix length: single hosts are /32 (v4) or /128 (v6)","netip is stricter than net.ParseCIDR: no spaces, no bare IPs - normalize input at the API boundary","Add the parseSourceRanges guard to any script or automation that writes network policies"],"tags":["go","netbird","acl","cidr","validation","management-api"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}