nats-io/nats-server · error

metadata incomplete

Error message

metadata incomplete

What it means

When decoding compression metadata for a stored block, the parser reads the algorithm byte and then a Uvarint original size. If binary.Uvarint returns n <= 0 (buffer truncated or malformed varint), there is not enough valid metadata to proceed, so it returns "metadata incomplete". From server/filestore.go's compression header decode path.

Source

Thrown at server/filestore.go:14494

	b[3] = byte(c.Algorithm)
	n := binary.PutUvarint(b[4:], c.OriginalSize)
	return b[:4+n]
}

func (c *CompressionInfo) UnmarshalMetadata(b []byte) (int, error) {
	c.Algorithm = NoCompression
	c.OriginalSize = 0
	if len(b) < 5 { // 4 + min 1 for uvarint uint64
		return 0, nil
	}
	if b[0] != 'c' || b[1] != 'm' || b[2] != 'p' {
		return 0, nil
	}
	var n int
	c.Algorithm = StoreCompression(b[3])
	c.OriginalSize, n = binary.Uvarint(b[4:])
	if n <= 0 {
		return 0, fmt.Errorf("metadata incomplete")
	}
	return 4 + n, nil
}

func (alg StoreCompression) Compress(buf []byte) ([]byte, error) {
	if len(buf) < checksumSize {
		return nil, fmt.Errorf("uncompressed buffer is too short")
	}
	bodyLen := int64(len(buf) - checksumSize)
	var output bytes.Buffer
	var writer io.WriteCloser
	switch alg {
	case NoCompression:
		return buf, nil
	case S2Compression:
		writer = s2.NewWriter(&output)
	default:
		return nil, fmt.Errorf("compression algorithm not known")

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Treat the block as corrupt and rebuild/consume the data from replicated peers or backups
  2. Verify disk integrity (fsck, SMART) if this recurs on the same volume
  3. Restore JetStream data from a verified backup taken with the server stopped
  4. Delete the corrupt consumer block and let the consumer state be recreated (redelivery handles the gap)

Example fix

null
Defensive patterns

Strategy: type-guard

Validate before calling

func blockMetadataLooksSane(b []byte) bool {
	if len(b) < 4 { return false }
	_, n := binary.Uvarint(b[4:])
	return n > 0
}

Type guard

func hasCompleteMetadata(b []byte) bool {
	if len(b) < 5 { return false }
	_, n := binary.Uvarint(b[4:])
	return n > 0
}

Try / catch

size, err := decodeCompressionMeta(b)
if err != nil && strings.Contains(err.Error(), "metadata incomplete") {
	// mark block corrupt, recover from replica/backup
	return errBlockCorrupt
}

Prevention

When it happens

Trigger: Decoding a compressed block whose bytes are truncated (short read from disk) or whose metadata region is corrupted so the varint size field is missing/malformed.

Common situations: Disk corruption or partial write of a JetStream block; truncating a store file manually; restoring an incomplete backup; reading past EOF on a damaged file.

Related errors


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