nats-io/nats-server · error
ErrNegativeEntrySize
ErrNegativeEntrySize
Error message
archive: negative entry size
What it means
ErrNegativeEntrySize is returned by the archive writer's WriteHeader when a Header describes negative sizes. An archive entry cannot have a negative header or payload byte count, so such a header is rejected before anything is written. It also guards against signed integer overflow when HeaderSize and PayloadSize are summed.
Source
Thrown at server/archive/archive.go:37
"errors"
"io"
)
const MagicBytes = "NATSARC1"
// maxNameLen bounds the entry name length accepted when reading an archive,
// avoiding an unbounded allocation on corrupt or malicious input. The name is
// the only variable-length field read directly from the stream.
const maxNameLen = 1 << 20
var (
ErrClosed = errors.New("archive: closed")
ErrInvalidArchive = errors.New("archive: invalid archive stream")
ErrIncompleteEntry = errors.New("archive: entry not fully written")
ErrNoActiveEntry = errors.New("archive: no active entry")
ErrWriteTooLong = errors.New("archive: write exceeds declared entry size")
ErrNilHeader = errors.New("archive: nil header")
ErrNegativeEntrySize = errors.New("archive: negative entry size")
)
// Header describes one archive entry.
//
// On the wire each entry is the encoded header fields followed by the payload.
// HeaderSize and PayloadSize describe how that payload is split (e.g. message
// headers vs. body); the payload length is their sum and is not stored
// separately. Sequence is always encoded, with 0 meaning "unset".
type Header struct {
Name string
HeaderSize int64
PayloadSize int64
Timestamp int64
Sequence uint64
}
func (h *Header) clone() *Header {
if h == nil {View on GitHub (pinned to 3a66a489d2)
Solutions
- Fix the caller so HeaderSize and PayloadSize are computed as non-negative values (check len() results before assignment)
- Validate header fields before calling WriteHeader and reject negative values upstream
- If sizes come from parsed input, clamp or reject values that don't fit in int64
Example fix
// before
hdr.PayloadSize := int64(len(body) - offset) // offset > len(body) yields negative
// after
if offset > int64(len(body)) {
return fmt.Errorf("invalid offset %d", offset)
}
hdr.PayloadSize = int64(len(body)) - offset Defensive patterns
Strategy: validation
Validate before calling
func validHeader(hdr *archive.Header) bool {
return hdr != nil && hdr.HeaderSize >= 0 && hdr.PayloadSize >= 0 &&
hdr.HeaderSize+hdr.PayloadSize >= 0
}
if !validHeader(hdr) {
return fmt.Errorf("invalid entry header sizes")
}
err := aw.WriteHeader(hdr) Try / catch
n, err := aw.WriteHeader(hdr)
if errors.Is(err, archive.ErrNegativeEntrySize) {
log.Fatalf("entry header has negative size: %v", err)
} Prevention
- Compute sizes from len() results that are checked non-negative
- Validate all header fields before WriteHeader
- Never cast unsigned lengths to signed ints without bounds checks
When it happens
Trigger: Calling WriteHeader with hdr.HeaderSize < 0, hdr.PayloadSize < 0, or with values whose sum (HeaderSize+PayloadSize) overflows to negative on 64-bit ints.
Common situations: Bugs in code computing entry sizes from other values (e.g. subtracting lengths), or unmarshaling a header from corrupt/hostile bytes producing negative sizes.
Related errors
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/6fd89eb89178e62b.
Report an issue: GitHub.