wavetermdev/waveterm · error

failed to write temp file %q: %w (also failed to remove temp

Error message

failed to write temp file %q: %w (also failed to remove temp file: %v)

What it means

AtomicWriteFile first writes the data to a temp file (<fileName>.tmp). If that write fails AND cleanup of the temp file also fails, the write error is wrapped together with the removal error so the developer sees both failures. The target file was never touched.

Source

Thrown at pkg/util/fileutil/fileutil.go:183

		if mode&charDevice == charDevice {
			return "character-special"
		}
		if mode&os.ModeDevice == os.ModeDevice {
			return "block-special"
		}
	}
	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/",

View on GitHub (pinned to a4447c1563)

Solutions

  1. Fix write permissions on the parent directory (chmod/chown) so both writing and removing the temp file succeed.
  2. Check disk space (df) and free space on the filesystem holding the file.
  3. Ensure fileName + ".tmp" is not a directory or owned by another process; remove the stale temp file manually.
  4. Retry the write after fixing the underlying condition, then re-run AtomicWriteFile.

Example fix

// before
err := fileutil.AtomicWriteFile("/etc/hosts", data, 0644) // permission denied, temp cleanup also denied

// after
if err := os.Chmod(filepath.Dir(target), 0755); err != nil { return err }
err := fileutil.AtomicWriteFile(target, data, 0644)
Defensive patterns

Strategy: try-catch

Validate before calling

// precheck writability of the target directory
d := filepath.Dir(fileName)
if fi, err := os.Stat(d); err != nil || !fi.IsDir() {
    return fmt.Errorf("bad target dir %s", d)
}
if err := syscall.Access(d, unix.W_OK); err != nil {
    return fmt.Errorf("dir %s not writable: %w", d, err)
}

Try / catch

// Go: inspect wrapped errors
if err := fileutil.AtomicWriteFile(f, data, 0644); err != nil {
    if strings.Contains(err.Error(), "failed to write temp file") {
        log.Printf("temp write failed (and cleanup failed): %v", err)
        // check permissions/disk space, remove stale <f>.tmp, retry
    }
}

Prevention

When it happens

Trigger: Calling AtomicWriteFile where writing fileName+".tmp" fails (bad permissions, read-only dir, disk full, path is a directory) and the subsequent os.Remove of the temp file also fails with a non-NotNotExist error (e.g. permission denied on the directory).

Common situations: Writing to a directory without write permission; disk full so even unlink bookkeeping/attributes fail; temp file path colliding with a directory or a file owned by another user.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/f483f9a3776736ba. Report an issue: GitHub.