wavetermdev/waveterm · error
invalid source path: %w
Error message
invalid source path: %w
What it means
After appId validation, RenameAppFile resolves the SOURCE file name via validateAndResolveFilePath and wraps any failure as 'invalid source path' (waveappstore.go:388-391). The resolver rejects absolute paths, '..' path traversal, and any path that escapes the app directory — this prevents renaming files outside ~/waveapps/<ns>/<app>.
Source
Thrown at pkg/waveappstore/waveappstore.go:390
return nil, err
}
return fileutil.ReplaceInFilePartial(filePath, edits)
}
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
}
View on GitHub (pinned to a4447c1563)
Solutions
- Pass fromFileName as a plain relative path inside the app, e.g. 'old.txt' or 'sub/dir/file.go'.
- Strip any leading '/' and resolve '..' segments before calling; reject them if the result escapes the app.
- If the goal is cross-app or cross-namespace moves, do ReadAppFile + WriteAppFile + DeleteAppFile instead of '..' traversal.
- Check the wrapped sub-error: it names the exact rule violated (absolute path / path traversal / escapes app directory).
Example fix
// before
waveappstore.RenameAppFile(appId, "/home/user/waveapps/local/app/old.txt", "new.txt") // absolute rejected
// after
err := waveappstore.RenameAppFile(appId, "old.txt", "new.txt") // relative to app dir
if err != nil && strings.Contains(err.Error(), "invalid source path") {
return fmt.Errorf("source must be a relative path inside the app: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
func safeRelName(name string) (string, error) {
if filepath.IsAbs(name) {
return "", fmt.Errorf("must be relative: %s", name)
}
clean := filepath.Clean(name)
if strings.HasPrefix(clean, "..") || strings.Contains(clean, string(filepath.Separator)+"..") {
return "", fmt.Errorf("traversal not allowed: %s", name)
}
return clean, nil
}
// run on fromFileName (and toFileName) before RenameAppFile Try / catch
err := waveappstore.RenameAppFile(appId, fromName, toName)
if err != nil {
var kind string
switch {
case strings.Contains(err.Error(), "invalid source path"):
kind = "source"
case strings.Contains(err.Error(), "invalid destination path"):
kind = "destination"
}
return fmt.Errorf("rename rejected (%s): %w", kind, err)
} Prevention
- Always pass plain relative paths like 'dir/file.txt' — never absolute paths or '..' segments.
- Sanitize user-typed paths in the UI before calling rename.
- For cross-app moves, use ReadAppFile + WriteAppFile + DeleteAppFile instead of traversal.
- Clean and re-check names with filepath.Clean plus a '..' prefix check.
When it happens
Trigger: Calling RenameAppFile / RenameAppFileCommand with fromFileName that is absolute ('/etc/passwd'), contains '..' segments ('../shared.txt'), cleans to escape the app dir, or otherwise fails validateAndResolveFilePath.
Common situations: Frontends forwarding user-typed paths that include leading '/' or '../'; code joining a base dir into fileName before calling (producing an absolute path); attempts to move files between apps by using '../otherapp/file' instead of two rename operations.
Related errors
- invalid app name: %w
- invalid new app name: %w
- potential path traversal detected for path %s
- invalid AIMessage: %w
- part %d: text type requires non-empty text field
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/2c1178cc3d1daab5.
Report an issue: GitHub.