wavetermdev/waveterm · error
invalid destination path: %w
Error message
invalid destination path: %w
What it means
RenameAppFile validates the destination file name by resolving it inside the app directory before performing the rename. validateAndResolveFilePath rejects absolute paths, '..' path traversal, and any path that escapes the app directory. The library wraps that failure as "invalid destination path" so callers know the destination fileName argument, not the filesystem, is the problem.
Source
Thrown at pkg/waveappstore/waveappstore.go:395
func RenameAppFile(appId string, fromFileName string, toFileName string) error {
if err := ValidateAppId(appId); err != nil {
return fmt.Errorf("invalid appId: %w", err)
}
appDir, err := GetAppDir(appId)
if err != nil {
return err
}
fromPath, err := validateAndResolveFilePath(appDir, fromFileName)
if err != nil {
return fmt.Errorf("invalid source path: %w", err)
}
toPath, err := validateAndResolveFilePath(appDir, toFileName)
if err != nil {
return fmt.Errorf("invalid destination path: %w", err)
}
if err := os.MkdirAll(filepath.Dir(toPath), 0755); err != nil {
return fmt.Errorf("failed to create destination directory: %w", err)
}
if err := os.Rename(fromPath, toPath); err != nil {
return fmt.Errorf("failed to rename file: %w", err)
}
return nil
}
func FormatGoFile(appId string, fileName string) error {
if err := ValidateAppId(appId); err != nil {
return fmt.Errorf("invalid appId: %w", err)
}
View on GitHub (pinned to a4447c1563)
Solutions
- Ensure toFileName is a relative path inside the app (e.g. "subdir/main.go"), not an absolute path
- Strip any leading '/' and resolve/eliminate any '..' components from toFileName before calling
- Join the destination with GetAppDir(appId) and confirm it stays within the app directory
- Call validateAndResolveFilePath-equivalent logic (filepath.Clean + prefix check) client-side to pre-validate
Example fix
// before RenameAppFile(appId, "main.go", "/tmp/newname.go") // after RenameAppFile(appId, "main.go", "src/newname.go")
Defensive patterns
Strategy: validation
Validate before calling
func validDestName(name string) bool {
if filepath.IsAbs(name) {
return false
}
clean := filepath.Clean(name)
return !strings.HasPrefix(clean, "..") && !strings.Contains(clean, string(filepath.Separator)+"..")
}
if !validDestName(toFileName) {
return errors.New("destination must be a relative path inside the app")
} Type guard
func isRelativeInApp(appDir, name string) bool {
if filepath.IsAbs(name) { return false }
clean := filepath.Clean(name)
if strings.HasPrefix(clean, "..") { return false }
full, _ := filepath.Abs(filepath.Join(appDir, clean))
root, _ := filepath.Abs(appDir)
return strings.HasPrefix(full, root+string(filepath.Separator))
} Try / catch
if err := RenameAppFile(appId, from, to); err != nil {
if strings.Contains(err.Error(), "invalid destination path") {
return fmt.Errorf("bad rename target %q: %w", to, err)
}
return err
} Prevention
- Always pass app-relative file names, never absolute paths or user-typed raw paths
- Normalize with filepath.Clean and reject '..' segments before calling
- Derive destinations from existing file listings rather than free-text input
When it happens
Trigger: Calling RenameAppFile (via RenameAppFileCommand) with a toFileName that is absolute (e.g. "/etc/passwd"), contains ".." segments (e.g. "../other/file.go"), or resolves outside ~/waveapps/<ns>/<app>.
Common situations: Users typing a destination path with leading '/' or '..' in a rename prompt; frontend code passing a full path instead of an app-relative name; path separators from Windows pasted into a rename input.
Related errors
- integer overflow
- Invalid command path: ${formatPath(path)}
- beginning of file
- procinfo: process not found
- bind tags must be self closing
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/f61a159415473e63.
Report an issue: GitHub.