fatedier/frp · error

failed to write temp file: %w

Error message

failed to write temp file: %w

What it means

Writing the serialized JSON to the temp file failed after it was successfully created. The temp file is closed and removed, and the in-memory mutation is rolled back, so store state stays consistent — but the change is lost.

Source

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

		return fmt.Errorf("failed to marshal JSON: %w", err)
	}

	dir := filepath.Dir(s.config.Path)
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return fmt.Errorf("failed to create directory: %w", err)
	}

	tmpPath := s.config.Path + ".tmp"

	f, err := os.OpenFile(tmpPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
	if err != nil {
		return fmt.Errorf("failed to create temp file: %w", err)
	}

	if _, err := f.Write(data); err != nil {
		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)
	}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Check free space: df -h <store-dir>
  2. Free space or raise the quota/sizeLimit, or move the store to a volume with headroom
  3. Inspect dmesg/SMART output if space is available but writes fail (failing disk)
  4. Retry the failed operation (Add/Update/Remove) after space is restored — the rollback kept state consistent

Example fix

# before
$ df -h /var/lib/frpc
Filesystem  Size Used Avail Use% Mounted on
overlay      10G  10G     0 100% /

# after: free space, then retry the Add/Update call
$ df -h /var/lib/frpc
overlay      10G  8G  2G  80% /
Defensive patterns

Strategy: try-catch

Validate before calling

func hasDiskSpace(path string, want uint64) bool {
	var st syscall.Statfs_t
	if err := syscall.Statfs(filepath.Dir(path), &st); err != nil {
		return true // unknown; let the write surface the real error
	}
	return uint64(st.Bavail)*uint64(st.Bsize) > want
}

Try / catch

if err := store.AddProxy(cfg); err != nil {
	if errors.Is(err, syscall.ENOSPC) {
		// alert, free space, then retry the Add — rollback kept state consistent
	} else {
		return err
	}
}

Prevention

When it happens

Trigger: ENOSPC (disk full) on the volume holding the store path; disk quota exceeded for the user; thin-provisioned volume out of space; I/O error from a failing disk (dmesg will show it).

Common situations: Long-running frpc on a small root disk or container overlay that filled up; CI environments with tiny tmpfs; k8s emptyDir with sizeLimit reached.

Related errors


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