wavetermdev/waveterm · error
failed to rename temp file %q to %q: %w (also failed to remo
Error message
failed to rename temp file %q to %q: %w (also failed to remove temp file: %v)
What it means
AtomicWriteFile writes to a temp file and then renames it onto the target. This error is returned when os.Rename fails and the subsequent attempt to remove the temp file also fails, wrapping both errors. The original target file is left untouched; a stale .tmp file may remain.
Source
Thrown at pkg/util/fileutil/fileutil.go:189
}
ext := strings.ToLower(filepath.Ext(path))
if mimeType, ok := StaticMimeTypeMap[ext]; ok {
return mimeType
}
return ""
}
func AtomicWriteFile(fileName string, data []byte, perm os.FileMode) error {
tmpFileName := fileName + TempFileSuffix
if err := os.WriteFile(tmpFileName, data, perm); err != nil {
if removeErr := os.Remove(tmpFileName); removeErr != nil && !os.IsNotExist(removeErr) {
return fmt.Errorf("failed to write temp file %q: %w (also failed to remove temp file: %v)", tmpFileName, err, removeErr)
}
return err
}
if err := os.Rename(tmpFileName, fileName); err != nil {
if removeErr := os.Remove(tmpFileName); removeErr != nil && !os.IsNotExist(removeErr) {
return fmt.Errorf("failed to rename temp file %q to %q: %w (also failed to remove temp file: %v)", tmpFileName, fileName, err, removeErr)
}
return err
}
return nil
}
var (
systemBinDirs = []string{
"/bin/",
"/usr/bin/",
"/usr/local/bin/",
"/opt/bin/",
"/sbin/",
"/usr/sbin/",
}
suspiciousPattern = regexp.MustCompile(`[:;#!&$\t%="|>{}]`)
flagPattern = regexp.MustCompile(` --?[a-zA-Z0-9]`)
)View on GitHub (pinned to a4447c1563)
Solutions
- Ensure the target path is not a directory and its parent has write permission.
- Ensure the temp file and target are on the same filesystem (write temp next to the target, which this function already does — so check for mount-point changes).
- Manually remove the stale fileName+".tmp" file, then retry.
- Check for processes locking the target (editors, sync clients, antivirus) and retry.
Example fix
// before
fileutil.AtomicWriteFile("/home/user/.config/wave", data, 0644) // ~/.config/wave is a directory
// after
if fi, err := os.Stat(target); err == nil && fi.IsDir() {
return fmt.Errorf("target %s is a directory", target)
}
return fileutil.AtomicWriteFile(target, data, 0644) Defensive patterns
Strategy: retry
Validate before calling
// ensure target is not a directory and temp file is absent
if fi, err := os.Stat(fileName); err == nil && fi.IsDir() {
return fmt.Errorf("target %s is a directory", fileName)
}
os.Remove(fileName + ".tmp") // ignore NotExist Try / catch
// Go: retry rename failures after cleanup
if err := fileutil.AtomicWriteFile(f, data, 0644); err != nil {
if strings.Contains(err.Error(), "failed to rename temp file") {
os.Remove(f + ".tmp")
time.Sleep(50 * time.Millisecond)
err = fileutil.AtomicWriteFile(f, data, 0644) // retry once
}
} Prevention
- Confirm the target path is a file, not a directory
- Keep temp and target on the same filesystem
- Avoid concurrent writers to the same target path
- Account for AV/sync tools that briefly lock files on Windows
When it happens
Trigger: os.Rename(tmpFileName, fileName) failing (target path is a directory, cross-device rename, target locked/permission issue) combined with os.Remove(tmpFileName) failing for a reason other than NotExist.
Common situations: Target path exists as a directory; /tmp-style cross-filesystem setups when temp and target are on different mounts; an open file handle or AV scanner holding the temp file on Windows; permission mismatch between temp and target directories.
Related errors
- failed to write temp file %q: %w (also failed to remove temp
- failed to rename file: %w
- failed to get app directory: %w
- failed to get builder executable path: %w
- build output not found: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/c7853f5ffb441e5c.
Report an issue: GitHub.