thanos-io/thanos · error

corrupted identifier

Error message

corrupted identifier

What it means

This is a minimal in-replica snappy framing reader (readNextChunk). A stream-identifier chunk (chunkTypeStreamIdentifier) must carry exactly the 6-byte body "sNaPpY"; any other length means the framed stream is corrupt, so iteration stops with this error.

Solutions

  1. Treat the postings entry as corrupt and evict it from the cache
  2. Re-encode/rebuild the cache from the index
  3. Verify storage medium health (fsck, disk SMART) if corruption recurs
Defensive patterns

Strategy: fallback

Validate before calling

func validateSnappyFraming(input []byte) error {
    if len(input) < 10 || !bytes.Contains(input, []byte("\xff\x06\x00\x00sNaPpY")) {
        return errors.New("missing snappy stream identifier")
    }
    return nil
}

Try / catch

it := newStreamedDiffVarintPostings(body, false)
for it.Next() {
    v := it.At()
}
if it.Err() != nil {
    if strings.Contains(it.Err().Error(), "corrupted identifier") {
        return evictCacheEntry(key) // treat as corrupt, refetch from index
    }
    return it.Err()
}

Prevention

When it happens

Trigger: Next() -> readNextChunk encountering a stream-identifier chunk whose chunkLen != 6 while parsing streamed snappy postings — truncated or bit-rotted encoded postings bytes.

Common situations: Disk corruption of cached postings; truncation during cache write/copy; decoding arbitrary bytes as streamed snappy.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/4add59cb5c81f6ae. Report an issue: GitHub.

Appendix: source

Thrown at pkg/store/postings_codec.go:253

	}

	// Read next chunk into it.db.B.
	chunkType := it.input[0]
	it.input = it.input[1:]

	if len(it.input) < 3 {
		it.err = io.ErrUnexpectedEOF
		return false
	}

	chunkLen := int(it.input[0]) | int(it.input[1])<<8 | int(it.input[2])<<16
	it.input = it.input[3:]

	switch chunkType {
	case chunkTypeStreamIdentifier:
		const magicBody = "sNaPpY"
		if chunkLen != len(magicBody) {
			it.err = fmt.Errorf("corrupted identifier")
			return false
		}
		if string(it.input[:len(magicBody)]) != magicBody {
			it.err = fmt.Errorf("got bad identifier %s", string(it.input[:6]))
			return false
		}
		it.input = it.input[6:]
		it.readSnappyIdentifier = true
		return it.readNextChunk(nil)
	case chunkTypeCompressedData:
		if !it.readSnappyIdentifier {
			it.err = fmt.Errorf("missing magic snappy marker")
			return false
		}
		if len(it.input) < 4 {
			it.err = io.ErrUnexpectedEOF
			return false
		}

View on GitHub (pinned to 35b8b99117)