thanos-io/thanos · error

read symbols

Error message

read symbols

What it means

Thrown when index.NewSymbols fails while loading the symbol table from the index file, using the offset recorded in the index-header TOC. It indicates the symbol table section of the source index is unreadable, or the index version recorded in the index-header does not match the actual index format.

Solutions

  1. Regenerate the index-header file (delete it from the bucket so Thanos recreates it from the index)
  2. Verify the index file integrity and that index-header and index belong to the same block
  3. Ensure Prometheus/Thanos versions are consistent with the block format versions
  4. Re-upload the affected block from a healthy source
Defensive patterns

Strategy: validation

Validate before calling

if st, err := os.Stat(indexPath); err != nil || st.Size() == 0 { /* restore/re-upload block before building index-header */ }

Try / catch

if err != nil && strings.Contains(err.Error(), "read symbols") { regenerate index-header; if persists, quarantine block }

Prevention

When it happens

Trigger: NewBinaryReader parses the index-header successfully but index.NewSymbols(r.b, r.indexVersion, toc.Symbols) fails because the symbol table offset is wrong, the symbol section is corrupt, or indexVersion (FormatV1/V2) is inconsistent with the data.

Common situations: Blocks uploaded by a different Prometheus/Thanos version than the reader expects; truncated index files; index-header generated from a different index than the one being read (mismatched pair in storage).

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at pkg/block/indexheader/binary_reader.go:693

	}
	r.version = int(r.b.Range(4, 5)[0])
	r.indexVersion = int(r.b.Range(5, 6)[0])

	r.indexLastPostingEnd = int64(binary.BigEndian.Uint64(r.b.Range(6, headerLen)))

	if r.version != BinaryFormatV1 {
		return errors.Errorf("unknown index header file version %d", r.version)
	}

	r.toc, err = newBinaryTOCFromByteSlice(r.b)
	if err != nil {
		return errors.Wrap(err, "read index header TOC")
	}

	// TODO(bwplotka): Consider contributing to Prometheus to allow specifying custom number for symbolsFactor.
	r.symbols, err = index.NewSymbols(r.b, r.indexVersion, int(r.toc.Symbols))
	if err != nil {
		return errors.Wrap(err, "read symbols")
	}

	var lastName, lastValue []byte
	if r.indexVersion == index.FormatV1 {
		// Earlier V1 formats don't have a sorted postings offset table, so
		// load the whole offset table into memory.
		r.postingsV1 = map[string]map[string]index.Range{}

		var prevRng index.Range
		if err := index.ReadPostingsOffsetTable(r.b, r.toc.PostingsOffsetTable, func(name, value []byte, postingsOffset uint64, _ int) error {
			if lastName != nil {
				prevRng.End = int64(postingsOffset - crc32.Size)
				r.postingsV1[string(lastName)][string(lastValue)] = prevRng
			}

			if _, ok := r.postingsV1[string(name)]; !ok {
				r.postingsV1[string(name)] = map[string]index.Range{}
				r.postings[string(name)] = nil // Used to get a list of labelnames in places.

View on GitHub (pinned to 35b8b99117)