netbirdio/netbird · error
peer and peer_groups cannot be set at the same time
Error message
peer and peer_groups cannot be set at the same time
What it means
Returned by NetworkRouter.Validate (management/server/networks/routers/types/router.go:76): a network router must select exactly one routing peer source, either a single peer or a list of peer groups, never both. Validation runs inside NewNetworkRouter, so it fires on router creation and update before anything is persisted.
Source
Thrown at management/server/networks/routers/types/router.go:76
AccountID: accountID,
NetworkID: networkID,
Peer: peer,
PeerGroups: peerGroups,
Masquerade: masquerade,
Metric: metric,
Enabled: enabled,
}
if err := r.Validate(); err != nil {
return nil, err
}
return r, nil
}
func (n *NetworkRouter) Validate() error {
if n.Peer != "" && len(n.PeerGroups) > 0 {
return errors.New("peer and peer_groups cannot be set at the same time")
}
if n.Peer == "" && len(n.PeerGroups) == 0 {
return errors.New("either peer or peer_groups must be provided")
}
return nil
}
func (n *NetworkRouter) ToAPIResponse() *api.NetworkRouter {
return &api.NetworkRouter{
Id: n.ID,
Peer: &n.Peer,
PeerGroups: &n.PeerGroups,
Masquerade: n.Masquerade,
Metric: n.Metric,
Enabled: n.Enabled,
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Remove either the peer field or the peer_groups field from the request payload so exactly one is set
- If you need both a specific peer and groups to route that network, create two separate routers for the network
Example fix
// before
{
"network_id": "nwr-1",
"peer": "p-1",
"peer_groups": ["grp-1"],
"enabled": true
}
// after
{
"network_id": "nwr-1",
"peer": "",
"peer_groups": ["grp-1"],
"enabled": true
} Defensive patterns
Strategy: validation
Validate before calling
// Enforce mutual exclusivity before sending the create/update request
if payload.Peer != "" && len(payload.PeerGroups) > 0 {
return fmt.Errorf("set either peer or peer_groups, not both")
} Try / catch
resp, err := createRouter(ctx, networkID, payload)
if err != nil {
if strings.Contains(err.Error(), "peer and peer_groups cannot be set at the same time") {
// clear one side of the payload and retry once
}
return err
} Prevention
- Model the router payload with one selectable field in UIs: selecting groups must clear peer and vice versa
- Omit unused fields (peer or peer_groups) from the JSON instead of sending empty values
- When migrating peer -> peer_groups, PATCH with an explicit empty peer and the new groups in one request
When it happens
Trigger: POST /api/networks/{networkId}/routers or PATCH on a router whose payload contains a non-empty peer field AND a non-empty peer_groups array at the same time.
Common situations: Migrating a router from a single peer to groups and leaving the old peer field in the payload; UI forms that keep a previously selected peer visible when the operator switches to group selection; API clients sending zero-valued-but-serialized fields that deserialize to a non-empty value.
Related errors
- router not part of network
- either peer or peer_groups must be provided
- posture checks name shouldn't be empty
- posture checks shouldn't be empty
- self deletion is not allowed
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/82047c0a133d0e53.
Report an issue: GitHub.