pingcap/tidb · error

invalid backup data file name: '%s'

Error message

invalid backup data file name: '%s'

What it means

Same invariant as restorer.go's GetFileRangeKey, duplicated in the snap-restore client (tikv_sender.go): backup data file names must look like '{store_id}_{region_id}_{epoch_version}_{key}_{ts}_{cf}.sst', and the range key is the name minus the '_{cf}.sst' suffix. A name with no underscore at all makes strings.LastIndex return -1 and triggers this panic.

Source

Thrown at br/pkg/restore/snap_client/tikv_sender.go:388

	splitter := split.NewRegionSplitterWithRegionIndexStep(split.NewClient(
		rc.pdClient,
		rc.pdHTTPClient,
		rc.tlsConf,
		maxSplitKeysOnce,
		rc.storeCount+1,
		splitClientOpts...,
	), rc.splitRegionIndexStep)
	splitter.SetCoarseScatter(rc.coarseScatter)

	return splitter.ExecuteSortedKeys(ctx, sortedSplitKeys)
}

func getFileRangeKey(f string) string {
	// the backup date file pattern is `{store_id}_{region_id}_{epoch_version}_{key}_{ts}_{cf}.sst`
	// so we need to compare with out the `_{cf}.sst` suffix
	idx := strings.LastIndex(f, "_")
	if idx < 0 {
		panic(fmt.Sprintf("invalid backup data file name: '%s'", f))
	}

	return f[:idx]
}

func (rc *SnapClient) sendRequestToStore(
	ctx context.Context,
	sendFn func(ectx context.Context, client importclient.ImporterClient, storeId uint64) error,
) error {
	stores, err := conn.GetAllTiKVStoresWithRetry(ctx, rc.pdClient, util.SkipTiFlash)
	if err != nil {
		return errors.Trace(err)
	}
	eg, ectx := errgroup.WithContext(ctx)
	pool := tidbutil.NewWorkerPool(uint(len(stores)), "check and compact")
	for _, store := range stores {
		if store.StatusAddress == "" || store.State != metapb.StoreState_Up {
			continue

View on GitHub (pinned to d01f9615c1)

Solutions

  1. List the backup sst prefix and delete or exclude files whose names do not match the canonical six-part underscore pattern.
  2. Re-run the restore from an untouched backup produced and read by the same BR/TiDB version.
  3. Validate the backup ('br backup validate' or restore dry-run) before the real restore.
  4. If BR itself wrote the offending name, collect the file list and backupmeta and file a bug at github.com/pingcap/br.

Example fix

// before
rangeKey := getFileRangeKey(f) // panics on 'README' or 'dat.sst'

// after: filter to canonical data files first
var reBackupSST = regexp.MustCompile(`^\d+_\d+_\d+_.+_.+_\w+\.sst$`)
if !reBackupSST.MatchString(f) {
    return nil
}
rangeKey := getFileRangeKey(f)
Defensive patterns

Strategy: validation

Validate before calling

var reBackupSST = regexp.MustCompile(`^\d+_\d+_\d+_.+_.+_\w+\.sst$`)

// filter the sst listing before passing names into restore/split logic
func filterCanonicalSSTs(names []string) []string {
    out := make([]string, 0, len(names))
    for _, n := range names {
        if reBackupSST.MatchString(n) {
            out = append(out, n)
        }
    }
    return out
}

Prevention

When it happens

Trigger: Snapshot restore reaching getFileRangeKey while building file groups / sorted split keys over the backup sst set, and encountering a file name without any '_' character - a stray file in the sst prefix, a truncated upload, or a renamed object in S3/GCS.

Common situations: Extra objects placed in the backup storage bucket next to the sst files; backups copied with tools that mangle names; interrupted uploads leaving non-canonical files; mismatch between the BR version that wrote the backup and the one restoring it.

Related errors


AI-assisted analysis of pingcap/tidb@d01f9615c1 (2026-08-15). Data as JSON: /api/errors/5fa795a572958cae. Report an issue: GitHub.