netbirdio/netbird · error
expected IPv6 address, got %s
Error message
expected IPv6 address, got %s
What it means
Thrown by wgaddr.Address.SetIPv6FromCompact when the compact byte blob decoded with netiputil.DecodePrefix yields a non-IPv6 address (prefix.Addr().Is6() is false, i.e. a plain v4 address). The method is the single entry point that fills the IPv6/IPv6Net overlay fields from serialized data (config file or network map from management), so the error means the sender put v4 data into the v6 slot. Note that Is6() accepts v4-mapped addresses like ::ffff:10.0.0.1, so this only fires for genuinely 4-byte/v4-encoded values.
Source
Thrown at client/iface/wgaddr/address.go:75
return netip.Prefix{}
}
return netip.PrefixFrom(addr.IPv6, addr.IPv6Net.Bits())
}
// SetIPv6FromCompact decodes a compact prefix (5 or 17 bytes) and sets the IPv6 fields.
// Returns an error if the bytes are invalid. A nil or empty input is a no-op.
//
//nolint:recvcheck
func (addr *Address) SetIPv6FromCompact(raw []byte) error {
if len(raw) == 0 {
return nil
}
prefix, err := netiputil.DecodePrefix(raw)
if err != nil {
return fmt.Errorf("decode v6 overlay address: %w", err)
}
if !prefix.Addr().Is6() {
return fmt.Errorf("expected IPv6 address, got %s", prefix.Addr())
}
addr.IPv6 = prefix.Addr()
addr.IPv6Net = prefix.Masked()
return nil
}
// ClearIPv6 removes the IPv6 overlay address, leaving only v4.
//
//nolint:recvcheck
func (addr *Address) ClearIPv6() {
addr.IPv6 = netip.Addr{}
addr.IPv6Net = netip.Prefix{}
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Check agent and management versions match; the compact prefix encoding (5 vs 17 bytes) changed across releases, so resync by re-registering or updating the peer
- Log the offending peer/account and skip the v6 assignment (ClearIPv6) instead of propagating the error, keeping the v4 overlay working
- If you control the producer, fix it to only call the v4 compact encoding for the v4 field and the 17-byte v6 encoding for the v6 field
- Reproduce by decoding the raw bytes with netiputil.DecodePrefix and printing prefix.Addr() to confirm which field is malformed
Example fix
// before
if err := addr.SetIPv6FromCompact(raw); err != nil {
return fmt.Errorf("set v6 overlay address: %w", err)
}
// after - v6 is soft, never break v4 for it
if err := addr.SetIPv6FromCompact(raw); err != nil {
log.Warnf("ignoring invalid v6 overlay payload, continuing v4-only: %v", err)
addr.ClearIPv6()
} Defensive patterns
Strategy: validation
Validate before calling
// before assigning, confirm the compact blob really carries a v6 prefix
func hasIPv6CompactPayload(raw []byte) bool {
if len(raw) == 0 {
return false
}
p, err := netiputil.DecodePrefix(raw)
return err == nil && p.Addr().Is6()
} Type guard
func isV6Prefix(p netip.Prefix) bool {
return p.IsValid() && p.Addr().Is6()
} Try / catch
err := addr.SetIPv6FromCompact(raw)
if err != nil {
if strings.Contains(err.Error(), "expected IPv6 address") {
log.Warnf("peer sent v4 in v6 slot, continuing v4-only: %v", err)
addr.ClearIPv6()
} else {
return err // decode failure is a different problem
}
} Prevention
- Keep agent and management versions aligned; the compact prefix wire format has changed across releases
- Never serialize a v4 compact prefix into the IPv6 field of the network map or state file
- Treat v6 as soft per NetBird convention: log and skip, never fail the v4 overlay because of v6 data
When it happens
Trigger: Management (or a hand-edited serialized state/config) writes an IPv4 prefix into the IPv6 field of the compact network map or config that SetIPv6FromCompact decodes. Concretely: agent upgrade/downgrade across versions that changed the compact encoding, a management bug, or test harnesses crafting the raw []byte with the wrong family.
Common situations: Version skew between agent and management after a partial upgrade; restoring a state file produced by a different agent build; self-hosted management patched to send v4 in the v6 slot. Per the repo's 'IPv6 is a soft feature' rule, a bad v6 payload should degrade to v4-only, not fail startup.
Related errors
- create IPv6 firewall: %w
- init ip6tables: %w
- create v6 router: %w
- create v6 acl manager: %w
- add peer filtering for %s: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/9edfef5152ea19f4.
Report an issue: GitHub.