nats-io/nats-server · critical

failed to write to temporary file: %w

Error message

failed to write to temporary file: %w

What it means

Returned when the file store fails to write the (possibly compressed/encrypted) block buffer to the temporary file during a block update. The write to tmpFD returned an OS-level error, so the update is aborted via errorCleanup. The original file remains untouched.

Source

Thrown at server/filestore.go:8062

		// We only need to write out the metadata header if compression is enabled.
		// If we're trying to uncompress the file on disk at this point, don't bother
		// writing metadata.
		meta := &CompressionInfo{
			Algorithm:    alg,
			OriginalSize: uint64(originalSize),
		}
		buf = append(meta.MarshalMetadata(), buf...)
	}

	// 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.

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Check free disk space on the stream's storage directory (df -h).
  2. Check filesystem health and mount status; dmesg for I/O errors.
  3. Verify permissions on the store directory and that no ulimit (nofile) is exhausted.
  4. Retry the publish/update once space is freed; errorCleanup removed the temp file so no manual cleanup is needed.

Example fix

// before: publish while disk is 100% full
nc.Publish(subj, payload)
// after: ensure capacity before writing, or monitor
// df -h /path/to/jetstream  ; free space or relocate store dir
Defensive patterns

Strategy: validation

Validate before calling

// before writing, check available space on the store volume
usage := diskUsage(storeDir)
if usage.Free < requiredBytes {
    return fmt.Errorf("insufficient disk space: %d free", usage.Free)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to write to temporary file") {
    // alert ops: check disk space / I/O on store volume
}

Prevention

When it happens

Trigger: tmpFD.Write(buf) returns a non-nil error while writing new block data to the temp file during a message block update (writeMsgs/update of a file-store stream).

Common situations: Disk full (ENOSPC), I/O errors on failing disks, temp directory on a full/unmounted filesystem, file descriptor limits hit, or permissions changed on the stream's data directory.

Related errors


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