{"record":{"id":"4714bbc351f599fc","repo":"nats-io/nats-server","slug":"processheaderpub-bad-or-missing-total-size-q","errorCode":null,"errorMessage":"processHeaderPub Bad or Missing Total Size: %q","messagePattern":"processHeaderPub Bad or Missing Total Size: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/client.go","lineNumber":2926,"sourceCode":"\t\tc.pa.size = parseSize(args[2])\n\t\tc.pa.hdb = args[1]\n\t\tc.pa.szb = args[2]\n\tcase 4:\n\t\tc.pa.subject = args[0]\n\t\tc.pa.reply = args[1]\n\t\tc.pa.hdr = parseSize(args[2])\n\t\tc.pa.size = parseSize(args[3])\n\t\tc.pa.hdb = args[2]\n\t\tc.pa.szb = args[3]\n\tdefault:\n\t\treturn fmt.Errorf(\"processHeaderPub Parse Error: %q\", arg)\n\t}\n\tif c.pa.hdr < 0 {\n\t\treturn fmt.Errorf(\"processHeaderPub Bad or Missing Header Size: %q\", arg)\n\t}\n\t// If number overruns an int64, parseSize() will have returned a negative value\n\tif c.pa.size < 0 {\n\t\treturn fmt.Errorf(\"processHeaderPub Bad or Missing Total Size: %q\", arg)\n\t}\n\tif c.pa.hdr > c.pa.size {\n\t\treturn fmt.Errorf(\"processHeaderPub Header Size larger then TotalSize: %q\", arg)\n\t}\n\tmaxPayload := atomic.LoadInt32(&c.mpay)\n\t// Use int64() to avoid int32 overrun...\n\tif maxPayload != jwt.NoLimit && int64(c.pa.size) > int64(maxPayload) {\n\t\t// If we are given the remaining read buffer (since we do blind reads\n\t\t// we may have the beginning of the message header/payload), we will\n\t\t// look for the tracing header and if found, we will generate a\n\t\t// trace event with the max payload ingress error.\n\t\t// Do this only for CLIENT connections.\n\t\tif c.kind == CLIENT && c.pa.hdr > 0 && len(remaining) > 0 {\n\t\t\thdr := remaining[:min(len(remaining), c.pa.hdr)]\n\t\t\tc.sendMsgTraceIngressErrEvent(hdr, ErrMaxPayload)\n\t\t}\n\t\tc.maxPayloadViolation(c.pa.size, maxPayload)\n\t\treturn ErrMaxPayload","sourceCodeStart":2908,"sourceCodeEnd":2944,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/client.go#L2908-L2944","documentation":"The total size field of an HMSG message parsed to a negative value. parseSize() returns -1 when the number is missing, non-numeric, or overflows int64, so the server cannot determine the total message length and rejects the protocol op.","triggerScenarios":"Client sends `HMSG <subject> <reply> <hdr> <total>` where total-size is non-numeric, negative, or exceeds int64 (e.g. 99999999999999999999), making c.pa.size < 0.","commonSituations":"Buggy client implementations computing the total size incorrectly, integer overflow when concatenating header+payload sizes, corrupted frames over the wire.","solutions":["Fix the client to compute total size as header size + payload size using a correct integer type","Ensure the size token is a plain decimal number with no sign, spaces, or suffixes","Inspect server debug logs / packet capture to find the malformed HMSG line and the client"],"exampleFix":"// before\nHMSG subj reply 5 -1\n// after\nHMSG subj reply 5 12","handlingStrategy":"validation","validationCode":"total := len(header) + len(payload)\nif total < 0 || total > math.MaxInt32 {\n    return errors.New(\"HMSG total size out of range\")\n}","typeGuard":"func isNonNegativeSize(token string) (int64, bool) {\n    n, err := strconv.ParseInt(token, 10, 64)\n    return n, err == nil && n >= 0\n}","tryCatchPattern":null,"preventionTips":["Compute total size in an int64 and cap it before sending","Never send -1 or signed sentinel values as sizes","Keep header and payload sizes consistent with what is actually written"],"tags":["protocol","parsing","overflow"],"backgroundTag":"nats-protocol-parse-error","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}