fatedier/frp · error

failed to rename temp file: %w

Error message

failed to rename temp file: %w

What it means

The final os.Rename(tmpPath, Path) failed, so the new store content never became live. Everything before (marshal, mkdir, write, fsync, close) succeeded; rename failures are typically locking or path-type issues rather than content issues. The temp file is removed on this path.

Source

Thrown at pkg/config/source/store.go:174

		f.Close()
		os.Remove(tmpPath)
		return fmt.Errorf("failed to write temp file: %w", err)
	}

	if err := f.Sync(); err != nil {
		f.Close()
		os.Remove(tmpPath)
		return fmt.Errorf("failed to sync temp file: %w", err)
	}

	if err := f.Close(); err != nil {
		os.Remove(tmpPath)
		return fmt.Errorf("failed to close temp file: %w", err)
	}

	if err := os.Rename(tmpPath, s.config.Path); err != nil {
		os.Remove(tmpPath)
		return fmt.Errorf("failed to rename temp file: %w", err)
	}

	return nil
}

func (s *StoreSource) persistOrRollbackUnlocked(rollback func()) error {
	if err := s.saveToFileUnlocked(); err != nil {
		rollback()
		return fmt.Errorf("failed to persist: %w", err)
	}
	return nil
}

// Store map selectors return the target map for generic helpers.
func proxyStoreEntries(s *StoreSource) map[string]v1.ProxyConfigurer {
	return s.proxies
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Retry the operation — transient Windows share violations usually clear once the scanner/editor releases the file
  2. Add a store-directory exclusion for the antivirus, or close the editor/tail holding the file
  3. Verify nothing replaced the destination with a directory: ls -la <dir>
  4. Check directory write permission (rename needs it even though the file itself is writable)

Example fix

# windows: exclude store dir from real-time AV scanning
Add-MpPreference -ExclusionPath 'C:\frp\store.json'

# then retry the failed Add/Update/Remove operation
Defensive patterns

Strategy: retry

Try / catch

err := store.AddProxy(cfg)
if err != nil && strings.Contains(err.Error(), "failed to rename temp file") {
	// common on Windows: AV/editor holding store.json. Safe to retry after a short delay;
	// rollback removed the temp file and reverted memory, so AddProxy is idempotent to re-run.
	time.Sleep(200 * time.Millisecond)
	err = store.AddProxy(cfg)
}

Prevention

When it happens

Trigger: On Windows, another process holds the destination open without FILE_SHARE_DELETE (antivirus scanners, editors tailing the file, backup software); the destination path exists as a DIRECTORY; EACCES on the containing directory; extremely rare EXDEV is impossible here because the temp file lives in the same directory.

Common situations: frpc on Windows with an AV scanning store.json at the wrong moment; a user watching the file in a tail/editor; a log-rotation/backup agent pinning it; destination accidentally replaced by a directory.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/c6fcf88ca0643490. Report an issue: GitHub.