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
- Treat the block as corrupt and rebuild/consume the data from replicated peers or backups
- Verify disk integrity (fsck, SMART) if this recurs on the same volume
- Restore JetStream data from a verified backup taken with the server stopped
- 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
- Stop the server before copying or restoring JetStream files
- Monitor disks for corruption; use replicas for state
- Never truncate store files manually
- Verify backups (checksums) before restoring
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
- failed to decompress block: %w
- rebuildState for block %d failed: %w
- failed to read original block from disk: %w
- failed to read existing metadata header: %w
- failed to decompress original block: %w
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/bc5441c73fb0b726.
Report an issue: GitHub.