OpenNHP/opennhp · warning

packet total size is incorrect

Error message

packet total size is incorrect

What it means

Device.RecvPrecheck compares the buffer's total length with headerSize plus the payload size declared in the packet header. A mismatch means the datagram is truncated, padded, or otherwise malformed, so parsing would read out of bounds; the packet is rejected before decryption.

Solutions

  1. Size the UDP receive buffer to the maximum NHP packet size so nothing is truncated
  2. Check that relays forward the datagram unmodified (same length)
  3. Log header size vs actual length to identify systematic truncation
  4. If sender-side, ensure SetHeaderTypeAndSize is called after the full payload is written

Example fix

// before
buf := make([]byte, 256) // too small for full packet
n, _ := conn.Read(buf)
// after
buf := make([]byte, nhpcore.MaxPacketSize)
n, _ := conn.Read(buf)
pkt := &nhpcore.Packet{Content: buf[:n]}
Defensive patterns

Strategy: validation

Validate before calling

if len(pkt.Content) < nhpcore.HeaderSize {
    return errors.New("truncated packet")
}
t, s := pkt.HeaderTypeAndSize()
if len(pkt.Content) != nhpcore.HeaderSize+s {
    return errors.New("length mismatch")
}

Type guard

func fullPacket(pkt *nhpcore.Packet) bool {
    t, s := pkt.HeaderTypeAndSize()
    return len(pkt.Content) == nhpcore.HeaderSize+s && t >= 0
}

Try / catch

if _, _, err := dev.RecvPrecheck(pkt); err != nil && strings.Contains(err.Error(), "total size is incorrect") {
    log.Warnf("malformed datagram (%d bytes) dropped", len(pkt.Content))
    return
}

Prevention

When it happens

Trigger: recvPacketRoutine, HandleRelayForward, or PacketToMsg reads a datagram where len(pkt.Content) != headerSize + s (declared header payload size), e.g. UDP truncation or a corrupted size field.

Common situations: Using a receive buffer smaller than the datagram so UDP truncates it; fragmentation issues on constrained networks; hand-crafted or fuzzed packets; relay forwarding with modified buffers.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/141590f1148888d0. Report an issue: GitHub.

Appendix: source

Thrown at nhp/core/packet.go:258

func (d *Device) RecvPrecheck(pkt *Packet) (int, int, error) {
	headerSize := pkt.Header().Size()

	// check type and payload size
	t, s := pkt.HeaderTypeAndSize()
	if t == NHP_KPL {
		if s == 0 {
			return t, s, nil
		} else {
			return t, s, fmt.Errorf("keepalive packet size is incorrect")
		}
	}
	if !d.CheckRecvHeaderType(t) {
		return t, s, fmt.Errorf("packet header type does not match device")
	}

	totalLen := len(pkt.Content)
	if totalLen != headerSize+s {
		return t, s, fmt.Errorf("packet total size is incorrect")
	}

	return t, s, nil
}

func (d *Device) AllocatePoolPacket() *Packet {
	buf := d.pool.Get()
	return &Packet{Buf: buf, Content: buf[:], PoolAllocated: true}
}

func (d *Device) ReleasePoolPacket(pkt *Packet) {
	if pkt != nil && pkt.Buf != nil && pkt.PoolAllocated {
		d.pool.Put(pkt.Buf)
		pkt.Buf = nil
		pkt.Content = nil
	}
}

View on GitHub (pinned to 6e04ca5ff0)