nats-io/nats-server · error

failed to close temporary file: %w

Error message

failed to close temporary file: %w

What it means

Returned when closing the temporary block file fails at the end of a file-store block update. Data was written and synced, but Close returned an error (often masking deferred flush issues), so the update aborts via errorCleanup.

Source

Thrown at server/filestore.go:8070

	}

	// Re-encrypt the block if necessary.
	if err = mb.encryptOrDecryptIfNeeded(buf); err != nil {
		return errorCleanup(err)
	}

	// Write the new block data (which might be compressed or encrypted) to the
	// temporary file.
	if n, err := tmpFD.Write(buf); err != nil {
		return errorCleanup(fmt.Errorf("failed to write to temporary file: %w", err))
	} else if n != len(buf) {
		return errorCleanup(fmt.Errorf("short write to temporary file (%d != %d)", n, len(buf)))
	}
	if err := tmpFD.Sync(); err != nil {
		return errorCleanup(fmt.Errorf("failed to sync temporary file: %w", err))
	}
	if err := tmpFD.Close(); err != nil {
		return errorCleanup(fmt.Errorf("failed to close temporary file: %w", err))
	}

	// Now replace the original file with the newly updated temp file.
	if err := os.Rename(tmpFN, origFN); err != nil {
		return fmt.Errorf("failed to move temporary file into place: %w", err)
	}

	// Since the message block might be retained in memory, make sure the
	// compression algorithm is up-to-date, since this will be needed when
	// compacting or truncating.
	mb.cmp = alg

	// Also update rbytes
	mb.rbytes = uint64(len(buf))

	return nil
}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Check open file descriptor limits (ulimit -n) and raise them if exhausted.
  2. Look for earlier I/O errors on the volume; Close often surfaces deferred write failures.
  3. Verify the container/host storage driver supports standard POSIX file semantics.
  4. Retry the operation after resolving the resource issue.

Example fix

// before: default low limit
// after: raise fd limit (systemd)
// LimitNOFILE=1048576
Defensive patterns

Strategy: validation

Validate before calling

// check fd headroom before high-throughput writes
if fds, err := countOpenFDs(pid); err == nil && float64(fds)/float64(fdLimit) > 0.8 {
    // raise LimitNOFILE or reduce concurrent streams
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to close temporary file") {
    // usually fd exhaustion or deferred I/O error; check ulimit and disk
}

Prevention

When it happens

Trigger: tmpFD.Close() returns an error after a successful write and Sync of new block data during a message block update.

Common situations: File descriptor exhaustion (too many open files), filesystem state issues after earlier I/O errors, or storage driver problems on virtualized/containerized filesystems.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/1c821dc9bafa2f93. Report an issue: GitHub.