{"record":{"id":"74fca51413666ad5","repo":"netbirdio/netbird","slug":"determine-destination-w","errorCode":null,"errorMessage":"determine destination: %w","messagePattern":"determine destination: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/internal/acl/manager.go","lineNumber":255,"sourceCode":"}\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}\n\n\tdPorts := convertPortInfo(rule.PortInfo)\n\n\taddedRule, err := d.firewall.AddRouteFiltering(rule.PolicyID, sources, destination, protocol, nil, dPorts, action)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"add route rule: %w\", err)\n\t}","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/internal/acl/manager.go#L237-L273","documentation":"Returned by applyRouteACL when determineDestination fails. Inside determineDestination the realistic failure is `parse destination: %w` from netip.ParsePrefix(rule.Destination) for non-dynamic rules; the dynamic branches (IsDynamic with domains, or the outdated-management fallback to the default prefix) always succeed. So the error means a static route ACL rule carried a Destination that is not a parseable CIDR.","triggerScenarios":"Rule with IsDynamic=false but a Destination holding a bare IP, hostname, or empty string; management/API writing a domain into Destination without setting IsDynamic; version mismatch where the agent expects CIDR-only destinations.","commonSituations":"Policies authored via API mixing up the domain field semantics (domains belong in rule.Domains with IsDynamic=true); dashboard edge cases; management validation gaps on older builds.","solutions":["Set Destination to a valid CIDR (a.b.c.d/32 for single hosts), or move the target into the domains field and enable the dynamic flag","Verify the management version validates route firewall destinations before dispatch; upgrade if not","Reconnect the peer / update the policy afterwards so the agent re-applies the corrected rule"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// policy-authoring guard: destination must be a CIDR unless the rule is dynamic\nfunc validRouteDestination(r *mgmProto.RouteFirewallRule) error {\n    if r.IsDynamic {\n        if len(r.Domains) == 0 {\n            return errors.New(\"dynamic rule without domains\")\n        }\n        return nil\n    }\n    if _, err := netip.ParsePrefix(r.Destination); err != nil {\n        return fmt.Errorf(\"destination %q must be a CIDR: %w\", r.Destination, err)\n    }\n    return nil\n}","typeGuard":"func isStaticCidrDestination(r *mgmProto.RouteFirewallRule) bool {\n    return !r.IsDynamic && isStrictCIDR(r.Destination)\n}","tryCatchPattern":"destination, err := determineDestination(rule, dynamicResolver, sources)\nif err != nil {\n    if strings.Contains(err.Error(), \"parse destination\") {\n        log.Warnf(\"rule %s has non-CIDR destination %q; fix policy or set IsDynamic\", rule.PolicyID, rule.Destination)\n        return \"\", err // drop rule rather than guess at an over-broad destination\n    }\n    return \"\", err\n}","preventionTips":["Domains belong in the domains field with IsDynamic=true, never in Destination","Express single hosts as /32 or /128 CIDRs","Upgrade management so it validates route ACL destinations before dispatching them to agents"],"tags":["go","netbird","acl","cidr","destination","policy"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}