nats-io/nats-server · error

processHeaderPub Bad or Missing Header Size: %q

Error message

processHeaderPub Bad or Missing Header Size: %q

What it means

NATS server failed to parse the header size field of an HMSG protocol message. parseSize() returned -1 (missing or non-numeric) or the field was absent, so the server cannot frame the header payload and closes the connection with this protocol error.

Source

Thrown at server/client.go:2922

	case 3:
		c.pa.subject = args[0]
		c.pa.reply = nil
		c.pa.hdr = parseSize(args[1])
		c.pa.size = parseSize(args[2])
		c.pa.hdb = args[1]
		c.pa.szb = args[2]
	case 4:
		c.pa.subject = args[0]
		c.pa.reply = args[1]
		c.pa.hdr = parseSize(args[2])
		c.pa.size = parseSize(args[3])
		c.pa.hdb = args[2]
		c.pa.szb = args[3]
	default:
		return fmt.Errorf("processHeaderPub Parse Error: %q", arg)
	}
	if c.pa.hdr < 0 {
		return fmt.Errorf("processHeaderPub Bad or Missing Header Size: %q", arg)
	}
	// If number overruns an int64, parseSize() will have returned a negative value
	if c.pa.size < 0 {
		return fmt.Errorf("processHeaderPub Bad or Missing Total Size: %q", arg)
	}
	if c.pa.hdr > c.pa.size {
		return fmt.Errorf("processHeaderPub Header Size larger then TotalSize: %q", arg)
	}
	maxPayload := atomic.LoadInt32(&c.mpay)
	// Use int64() to avoid int32 overrun...
	if maxPayload != jwt.NoLimit && int64(c.pa.size) > int64(maxPayload) {
		// If we are given the remaining read buffer (since we do blind reads
		// we may have the beginning of the message header/payload), we will
		// look for the tracing header and if found, we will generate a
		// trace event with the max payload ingress error.
		// Do this only for CLIENT connections.
		if c.kind == CLIENT && c.pa.hdr > 0 && len(remaining) > 0 {
			hdr := remaining[:min(len(remaining), c.pa.hdr)]

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Fix the client to always emit a valid non-negative integer header size in HMSG before the total size
  2. Upgrade or patch the client library so HMSG framing matches the NATS protocol spec
  3. Check for proxies/middleboxes corrupting the TCP stream between client and server
  4. Capture the wire traffic (or server log with debug enabled) to identify the offending client and its exact HMSG line

Example fix

// before (malformed frame)
HMSG subject reply 
// after (valid frame: hdr=5, total=7)
HMSG subject reply 5 7
Defensive patterns

Strategy: validation

Validate before calling

func validHMSG(subject, reply string, hdr, total int) bool {
    return hdr >= 0 && total >= 0 && hdr <= total && len(subject) > 0
}

Type guard

func isNonNegativeSize(token string) (int64, bool) {
    n, err := strconv.ParseInt(token, 10, 64)
    return n, err == nil && n >= 0
}

Prevention

When it happens

Trigger: Client sends `HMSG <subject> <reply> <hdr-size> <total-size>` with a missing, empty, or non-numeric header-size token (e.g. `HMSG foo abc 10`), causing processHeaderPub to see c.pa.hdr < 0.

Common situations: Hand-rolled or buggy client protocol implementations, a client/library version mismatch producing malformed wire frames, corrupted frames from a broken TCP middlebox or proxy rewriting bytes.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/611d50904fdf90c4. Report an issue: GitHub.