thanos-io/thanos · error

unexpected meta file

Error message

unexpected meta file: %s version: %d

What it means

After unmarshaling meta.json successfully, loadMeta validates that metadata.Meta.Version equals metadata.TSDBVersion1. If the version field differs, it throws errors.Errorf with this message and the block is rejected during sync. This guards against blocks written by incompatible TSDB meta.json schema versions.

Solutions

  1. Check the block's meta.json "version" field; ensure it is 1 (TSDBVersion1).
  2. Upgrade Thanos to a version that supports the block's meta.json version if it was produced by newer tooling.
  3. Re-create/re-upload the block from a compatible Prometheus/Compactor version rather than editing version by hand.
  4. Remove the incompatible block from the bucket if it is not needed.

Example fix

// before: meta.json with wrong version
{"ulid":"01ARZ3NDEKTSV4RRFFQ69G5FAV","version":2}
// after: re-upload block produced with supported schema
{"ulid":"01ARZ3NDEKTSV4RRFFQ69G5FAV","version":1}
Defensive patterns

Strategy: validation

Validate before calling

var meta struct {
    Version int `json:"version"`
}
if err := json.Unmarshal(metaContent, &meta); err != nil || meta.Version != 1 {
    // reject before sync: block meta.json version unsupported
}

Type guard

func isVersionMismatchError(err error) bool {
    return strings.Contains(err.Error(), "unexpected meta file")
}

Try / catch

if _, err := fetcher.FetchMetadata(ctx, filtered); err != nil {
    if strings.Contains(err.Error(), "unexpected meta file") {
        // identify the block, verify its meta.json version, upgrade Thanos or drop the block
    }
}

Prevention

When it happens

Trigger: Syncing (fetchMetadata) a block whose meta.json has version != 1 — e.g. a meta.json with "version": 2 or higher, or version 0/missing after hand-editing.

Common situations: Blocks produced by newer Prometheus/Thanos with an upgraded meta.json schema being consumed by an older Thanos; manually rewritten meta.json omitting or zeroing the version field; forged/hand-crafted test blocks.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at pkg/block/fetcher.go:500

	}
	if err != nil {
		return nil, errors.Wrapf(err, "get meta file: %v", metaFile)
	}

	defer runutil.CloseWithLogOnErr(f.logger, r, "close bkt meta get")

	metaContent, err := io.ReadAll(r)
	if err != nil {
		return nil, errors.Wrapf(err, "read meta file: %v", metaFile)
	}

	m := &metadata.Meta{}
	if err := json.Unmarshal(metaContent, m); err != nil {
		return nil, errors.Wrapf(ErrorSyncMetaCorrupted, "meta.json %v unmarshal: %v", metaFile, err)
	}

	if m.Version != metadata.TSDBVersion1 {
		return nil, errors.Errorf("unexpected meta file: %s version: %d", metaFile, m.Version)
	}

	// Best effort cache in local dir.
	if f.cacheDir != "" {
		if err := os.MkdirAll(cachedBlockDir, os.ModePerm); err != nil {
			level.Warn(f.logger).Log("msg", "best effort mkdir of the meta.json block dir failed; ignoring", "dir", cachedBlockDir, "err", err)
		}

		if err := m.WriteToDir(f.logger, cachedBlockDir); err != nil {
			level.Warn(f.logger).Log("msg", "best effort save of the meta.json to local dir failed; ignoring", "dir", cachedBlockDir, "err", err)
		}
	}
	return m, nil
}

type response struct {
	metas              map[ulid.ULID]*metadata.Meta
	partial            map[ulid.ULID]error

View on GitHub (pinned to 35b8b99117)