vitessio/vitess · error

failed to parse backup path %q: %w

Error message

failed to parse backup path %q: %w

What it means

ListBackups on FileBackupStorage first validates the requested directory with fileutil.SafePathJoin to prevent path traversal; if the joined path is not safely under FileBackupStorageRoot, this error is returned wrapping the underlying reason. The %q prints the (possibly empty) path value alongside the cause.

Source

Thrown at go/vt/mysqlctl/filebackupstorage/file.go:162

	stat := fbh.fbs.params.Stats.Scope(stats.Operation("File:Read"))
	return ioutil.NewMeteredReadCloser(f, stat.TimedIncrementBytes), nil
}

// FileBackupStorage implements BackupStorage for local file system.
type FileBackupStorage struct {
	params backupstorage.Params
}

func newFileBackupStorage(params backupstorage.Params) *FileBackupStorage {
	return &FileBackupStorage{params}
}

// ListBackups is part of the BackupStorage interface
func (fbs *FileBackupStorage) ListBackups(ctx context.Context, dir string) ([]backupstorage.BackupHandle, error) {
	// Check dir is not a directory traversal.
	path, err := fileutil.SafePathJoin(FileBackupStorageRoot, dir)
	if err != nil {
		return nil, fmt.Errorf("failed to parse backup path %q: %w", path, err)
	}

	fi, err := os.ReadDir(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	result := make([]backupstorage.BackupHandle, 0, len(fi))
	for _, info := range fi {
		if !info.IsDir() {
			continue
		}
		if info.Name() == "." || info.Name() == ".." {
			continue
		}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Pass a relative directory path that resolves strictly inside FileBackupStorageRoot.
  2. Strip or normalize '..' segments and leading slashes from user-supplied dir values before calling.
  3. Inspect the wrapped error from SafePathJoin to see which rule the path violated.

Example fix

// before
fbs.ListBackups(ctx, "/etc")
// after
fbs.ListBackups(ctx, "keyspace-shard-name")
Defensive patterns

Strategy: validation

Validate before calling

func safeBackupDir(dir string) bool {
	return dir != "" && !strings.Contains(dir, "..") && !filepath.IsAbs(dir)
}
if !safeBackupDir(userDir) { return errors.New("invalid backup dir") }

Try / catch

handles, err := fbs.ListBackups(ctx, dir)
if err != nil {
	return fmt.Errorf("list backups for %q: %w", dir, err)
}

Prevention

When it happens

Trigger: Calling ListBackups with a dir containing '..' or absolute-path components that escape the backup storage root; a dir that SafePathJoin rejects for any other reason.

Common situations: Automated scripts interpolating user or keyspace/table input into the backup dir path; path separators mixed ('/' vs OS separator) or a leading '/' making the path absolute; malicious or buggy input attempting traversal.

Understand the failure class

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/2d5a5977833183be. Report an issue: GitHub.