thanos-io/thanos · error

read convertedFromBLIDs field from parquet metadata file

Error message

read convertedFromBLIDs field from parquet metadata file: %v

What it means

Returned when field 6 (convertedFromBLIDs) of the parquet metadata protobuf message is present but fc.String() returns !ok — i.e. the field's wire type is not a string/bytes field as expected. Note the code wraps the (usually nil) err, so the wrap message carries the path but no underlying cause.

Solutions

  1. Regenerate the parquet metadata with a matching converter version
  2. Check whether the converter's proto definition changed field 6's type; align reader/writer versions
  3. Delete the offending metadata file if it is unrecoverable
Defensive patterns

Strategy: type-guard

Type guard

func isStringField(fc *easyproto.FieldContext) bool {
    return fc.FieldNum == 6 && fc.String() != nil
}

Try / catch

u, ok := fc.String()
if !ok { return fmt.Errorf("field 6 of %s is not a string", path) }

Prevention

When it happens

Trigger: A parquet metadata file whose field 6 is encoded with an unexpected wire type (varint/fixed instead of length-delimited) — produced by a schema mismatch or a corrupt/truncated file.

Common situations: Parquet converter version writing a different proto schema for field 6; manually edited or corrupted metadata files.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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

Appendix: source

Thrown at pkg/block/fetcher.go:1250

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

	content, err := io.ReadAll(r)
	if err != nil {
		return nil, errors.Wrapf(err, "read parquet metadata file: %v", path)
	}

	var fc easyproto.FieldContext
	for len(content) > 0 {
		content, err = fc.NextField(content)
		if err != nil {
			return nil, errors.Wrapf(err, "read next field from parquet metadata file: %v", path)
		}
		switch fc.FieldNum {
		case 6:
			u, ok := fc.String()
			if !ok {
				return nil, errors.Wrapf(err, "read convertedFromBLIDs field from parquet metadata file: %v", path)
			}
			id, err := ulid.Parse(u)
			if err != nil {
				return nil, errors.Wrapf(err, "parse block ID %q from parquet metadata file: %v", u, path)
			}
			migratedBlocks[id] = struct{}{}
		}
	}

	return migratedBlocks, nil
}

// IgnoreDeletionMarkFilter is a filter that filters out the blocks that are marked for deletion after a given delay.
// The delay duration is to make sure that the replacement block can be fetched before we filter out the old block.
// Delay is not considered when computing DeletionMarkBlocks map.
// Not go-routine safe.
type IgnoreDeletionMarkFilter struct {
	logger      log.Logger

View on GitHub (pinned to 35b8b99117)