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
- Fix the client to always emit a valid non-negative integer header size in HMSG before the total size
- Upgrade or patch the client library so HMSG framing matches the NATS protocol spec
- Check for proxies/middleboxes corrupting the TCP stream between client and server
- 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
- Always emit HMSG as: subject [reply] hdrSize totalSize, with hdrSize a non-negative integer
- Compute totalSize = hdrSize + len(payload) before writing the frame
- Use a maintained NATS client library instead of hand-rolled protocol frames
- Test frames against a local nats-server with debug logging enabled
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
- processPub Parse Error: %q
- bad message header detected
- processHeaderPub Parse Error: %q
- processHeaderPub Bad or Missing Total Size: %q
- processHeaderPub Header Size larger then TotalSize: %q
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/611d50904fdf90c4.
Report an issue: GitHub.