ipfs/kubo · error

syncing temp file: %w

Error message

syncing temp file: %w

What it means

`writeBinaryToTempFile` calls `f.Sync()` to guarantee the staged binary bytes reached stable storage before the file is used to replace the live binary. This error wraps a failing fsync; kubo aborts rather than atomically swapping in a binary whose durability is unverified.

Source

Thrown at core/commands/update.go:738

	pattern := migrations.ExeName(fmt.Sprintf("ipfs-%s-*", ver))
	f, err := os.CreateTemp("", pattern)
	if err != nil {
		return "", fmt.Errorf("creating temp file: %w", err)
	}
	defer func() {
		if cerr := f.Close(); cerr != nil && err == nil {
			err = fmt.Errorf("closing temp file: %w", cerr)
		}
		if err != nil {
			os.Remove(f.Name())
		}
	}()

	if _, err = f.Write(data); err != nil {
		return "", fmt.Errorf("writing temp file: %w", err)
	}
	if err = f.Sync(); err != nil {
		return "", fmt.Errorf("syncing temp file: %w", err)
	}
	if err = f.Chmod(0o755); err != nil {
		return "", fmt.Errorf("chmod temp file: %w", err)
	}
	return f.Name(), nil
}

// extractBinaryFromArchive extracts the kubo/ipfs binary from a tar.gz or zip archive.
func extractBinaryFromArchive(data []byte) ([]byte, error) {
	binName := migrations.ExeName("ipfs")

	// Try tar.gz first (Unix releases), then zip (Windows releases).
	result, tarErr := extractFromTarGz(data, binName)
	if tarErr == nil {
		return result, nil
	}

	result, zipErr := extractFromZip(data, binName)

View on GitHub (pinned to 329838acdf)

Solutions

  1. Point TMPDIR at a standard local filesystem: `export TMPDIR=/var/tmp` (ext4/xfs/btrfs) and rerun the update.
  2. Check `dmesg` for device I/O errors and run fsck if indicated.
  3. If on a network/FUSE mount by necessity, stage via a local dir first — the update flow always uses the OS temp dir, so TMPDIR is the lever.
  4. Retry once after a transient failure; the partial file is cleaned up automatically.

Example fix

# before
export TMPDIR=/mnt/nfs/tmp
ipfs update install v0.30.0   # syncing temp file: ... invalid argument

# after
export TMPDIR=/var/tmp
ipfs update install v0.30.0
Defensive patterns

Strategy: fallback

Validate before calling

// verify fsync works on the temp dir before updating
dir := os.TempDir()
probe, _ := os.CreateTemp(dir, ".fsync-probe-*")
if err := probe.Sync(); err != nil {
	// fsync unsupported here: switch TMPDIR to a local FS first
}
probe.Close()
os.Remove(probe.Name())

Type guard

func supportsFsync(dir string) bool {
	f, err := os.CreateTemp(dir, ".probe-*")
	if err != nil {
		return false
	}
	defer f.Close()
	defer os.Remove(f.Name())
	return f.Sync() == nil
}

Try / catch

path, err := writeBinaryToTempFile(data, ver)
if err != nil {
	if strings.Contains(err.Error(), "syncing temp file") {
		// fallback: repoint TMPDIR to a local POSIX filesystem and retry
		os.Setenv("TMPDIR", "/var/tmp")
		return retryUpdate()
	}
	return err
}

Prevention

When it happens

Trigger: `ipfs update install` when fsync on the temp executable fails: unsupported filesystem (some FUSE/NFS mounts), pending I/O error on the descriptor, or device-level failure.

Common situations: TMPDIR on NFS/SMB or a FUSE mount that rejects fsync; flaky external drive as TMPDIR; overlayfs quirks in restricted containers; storage hardware failures.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/e479e4cec46b723d. Report an issue: GitHub.