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
- Pass a relative directory path that resolves strictly inside FileBackupStorageRoot.
- Strip or normalize '..' segments and leading slashes from user-supplied dir values before calling.
- 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
- Never pass raw user input as backup dir; build from keyspace/shard identifiers
- Keep dir paths relative and slash-consistent
- Add unit tests for traversal attempts ('..', absolute paths) in tooling
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ReadFile cannot be called on read-write backup
- AddFile cannot be called on read-only backup
- EndBackup cannot be called on read-only backup
- AbortBackup cannot be called on read-only backup
- ReadFile cannot be called on read-write backup
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/2d5a5977833183be.
Report an issue: GitHub.