nats-io/nats-server · critical
failed to move temporary file into place: %w
Error message
failed to move temporary file into place: %w
What it means
Returned when os.Rename(tmpFN, origFN) fails while swapping the updated temporary block file into place after a successful write/sync/close. The new block data is fully written but could not atomically replace the original file, so the update fails with this wrapped error.
Source
Thrown at server/filestore.go:8075
}
// 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
}
// Lock should be held.
func (mb *msgBlock) decompressIfNeeded(buf []byte) ([]byte, error) {
var meta CompressionInfo
if n, err := meta.UnmarshalMetadata(buf); err != nil {
// There was a problem parsing the metadata header of the block.View on GitHub (pinned to 3a66a489d2)
Solutions
- Ensure the entire JetStream store directory is on the same filesystem (no split symlinks/bind mounts).
- Verify write permission on the stream's data directory for the nats process user.
- Stop backup/AV agents from holding or removing files under the store directory mid-update.
- Retry the update once the directory state is fixed; the temp file may need manual removal if errorCleanup missed it.
Example fix
// before: split filesystems StoreDir: /data/jetstream # with symlink to /mnt/other/blockdir // after: single filesystem StoreDir: /data/jetstream # entire tree on one volume
Defensive patterns
Strategy: validation
Validate before calling
// ensure store dir is one filesystem and writable before starting
info1, _ := os.Stat(storeDir)
dev := info1.Sys().(*syscall.Stat_t).Dev
if symlinkedAcrossDevices(storeDir) {
return fmt.Errorf("store dir spans multiple filesystems")
}
if !writable(storeDir) {
return fmt.Errorf("no write permission on %s", storeDir)
} Try / catch
if err != nil && strings.Contains(err.Error(), "failed to move temporary file into place") {
// check for EXDEV / permission issues; may need to remove leftover temp files
} Prevention
- Keep the entire JetStream store tree on a single filesystem; avoid split symlinks/bind mounts.
- Ensure the nats user owns the store directory with write permission.
- Exclude the store directory from backup/AV scanning that locks files.
- Clean leftover *.tmp files after failures.
When it happens
Trigger: os.Rename fails during the final commit step of a message block update — replacing the original block file with the temp file.
Common situations: Temp file and target on different filesystems (store dir partially relocated or symlinked), missing write permission on the directory (rename requires dir write), the original file removed/locked by backup agents, or cross-device link (EXDEV) errors in container volume setups.
Related errors
- failed to write to temporary file: %w
- short write to temporary file (%d != %d)
- failed to close temporary file: %w
- fileStore requires file storage type in config
- filestore max block size is %s
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/ce9ae38b8fb6d71c.
Report an issue: GitHub.