nats-io/nats-server · error

snapshot message bytes exceed reserved restore size

Error message

snapshot message bytes exceed reserved restore size

What it means

Validation guard during restore: the computed on-disk stored size for the message (derived from subject length, header size, and payload size for the storage backend) overflows int64 when cast from its unsigned raw computation. This is a defensive arithmetic-overflow check that fires only for absurd header values, i.e. a corrupt or crafted archive.

Source

Thrown at server/stream_backup.go:492

		if hdr.HeaderSize < 0 || hdr.PayloadSize < 0 || hdr.PayloadSize > math.MaxInt64-hdr.HeaderSize {
			return nil, fmt.Errorf("invalid message lengths for sequence %d", seq)
		}
		declaredSize := hdr.HeaderSize + hdr.PayloadSize
		if hdr.HeaderSize > mp || hdr.PayloadSize > mp-hdr.HeaderSize {
			return nil, fmt.Errorf("message sequence %d exceeds maximum payload size", seq)
		}
		if mms := int64(cfg.MaxMsgSize); mms >= 0 && (hdr.HeaderSize > mms || hdr.PayloadSize > mms-hdr.HeaderSize) {
			return nil, fmt.Errorf("message sequence %d exceeds maximum message size", seq)
		}
		var storedSizeRaw uint64
		switch cfg.Storage {
		case MemoryStorage:
			storedSizeRaw = memStoreMsgSizeRaw(len(hdr.Name), int(hdr.HeaderSize), int(hdr.PayloadSize))
		default:
			storedSizeRaw = fileStoreMsgSizeRaw(len(hdr.Name), int(hdr.HeaderSize), int(hdr.PayloadSize))
		}
		if storedSizeRaw > math.MaxInt64 {
			return nil, fmt.Errorf("snapshot message bytes exceed reserved restore size")
		}
		storedSize := int64(storedSizeRaw)
		if additional := storedSize - restoreRemaining; additional > 0 {
			jsa.updateUsage(tier, cfg.Storage, additional)
			restoreRemaining += additional
			if err := checkUsageLimits(); err != nil {
				return nil, err
			}
		}
		buf, err := io.ReadAll(tr)
		if err != nil {
			return nil, fmt.Errorf("failed to read message sequence %d: %w", seq, err)
		}
		if hdr.HeaderSize > int64(len(buf)) {
			return nil, fmt.Errorf("failed to parse message sequence %d: invalid header length", seq)
		}
		if int64(len(buf)) != declaredSize {
			return nil, fmt.Errorf("failed to read message sequence %d: unexpected payload size", seq)

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Regenerate the backup archive; stored-size overflow implies corrupted length fields in the current one
  2. Verify the archive was produced by a compatible official server version
  3. Validate header/payload lengths of archive entries before restore if importing external data
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/stream_backup.go:492 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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