netbirdio/netbird · error

decode v6 overlay address: %w

Error message

decode v6 overlay address: %w

What it means

Address.SetIPv6FromCompact decodes a compact prefix (5 or 17 bytes) via netiputil.DecodePrefix and applies it to the IPv6 fields. This error wraps the decode failure: wrong byte length, invalid embedded prefix length, or otherwise malformed bytes. Nil or empty input is a documented no-op and never errors; a decoded non-IPv6 result fails the separate Is6 check instead.

Source

Thrown at client/iface/wgaddr/address.go:72

// IPv6Prefix returns the v6 host address with its network prefix length, or a zero prefix if none.
func (addr Address) IPv6Prefix() netip.Prefix {
	if !addr.HasIPv6() {
		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

  1. Validate the byte length before decoding (empty, 5, or 17 bytes for the compact encoding)
  2. Confirm management and agent run compatible versions of the network map format
  3. Re-register the peer (netbird down/up) to fetch a fresh network map
  4. If it persists, inspect the stored state or protobuf payload for corruption

Example fix

// before
var a wgaddr.Address
if err := a.SetIPv6FromCompact(raw); err != nil {
    return err
}

// after
if n := len(raw); n != 0 && n != 5 && n != 17 {
    return fmt.Errorf("invalid compact prefix length %d", n)
}
if err := a.SetIPv6FromCompact(raw); err != nil {
    return err
}
Defensive patterns

Strategy: type-guard

Type guard

func isValidCompactPrefix(raw []byte) bool {
    n := len(raw)
    return n == 0 || n == 5 || n == 17
}

Try / catch

if err := addr.SetIPv6FromCompact(raw); err != nil {
    log.Warnf("ignoring malformed v6 overlay address: %v", err)
    addr.ClearIPv6() // keep the IPv4 path alive
}

Prevention

When it happens

Trigger: Decoding the compact IPv6 network bytes received from the management network map or read from stored state when they are truncated, sized for a different version of the format, or corrupt.

Common situations: Management and agent version mismatch on the compact v6 format; corrupted persisted state after an unclean shutdown; a peer or setup flow writing wrong-length bytes into the field.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/225c0a82c84895fa. Report an issue: GitHub.