hashicorp/nomad · error
failed to create temp snapshot file: %v
Error message
failed to create temp snapshot file: %v
What it means
Restore() streams a snapshot archive into Raft without buffering it in memory, so it first creates a scratch temp file via os.CreateTemp. This error wraps any failure from that temp file creation, with the underlying os error appended. It indicates the process could not obtain a temporary file, usually an OS/environment problem rather than corrupted snapshot data.
Source
Thrown at helper/snapshot/snapshot.go:269
// Restore takes the snapshot from the reader and attempts to apply it to the
// given Raft instance.
func Restore(logger hclog.Logger, in io.Reader, r *raft.Raft) error {
// Wrap the reader in a gzip decompressor.
decomp, err := gzip.NewReader(&readWrapper{in, 0})
if err != nil {
return fmt.Errorf("failed to decompress snapshot: %v", err)
}
defer func() {
if err := decomp.Close(); err != nil {
logger.Error("Failed to close snapshot decompressor", "error", err)
}
}()
// Make a scratch file to receive the contents of the snapshot data so
// we can avoid buffering in memory.
snap, err := os.CreateTemp("", "snapshot")
if err != nil {
return fmt.Errorf("failed to create temp snapshot file: %v", err)
}
defer func() {
if err := snap.Close(); err != nil {
logger.Error("Failed to close temp snapshot", "error", err)
}
if err := os.Remove(snap.Name()); err != nil {
logger.Error("Failed to clean up temp snapshot", "error", err)
}
}()
// Read the archive.
var metadata raft.SnapshotMeta
if err := read(decomp, &metadata, snap); err != nil {
return fmt.Errorf("failed to read snapshot file: %v", err)
}
if err := concludeGzipRead(decomp); err != nil {
return errView on GitHub (pinned to 482b49bf1a)
Solutions
- Check the wrapped %v cause: verify the temp directory exists, is writable, and has free space (df, ls -ld $TMPDIR).
- Set TMPDIR (or os.TempDir behavior) to a writable path before running the process.
- Check filesystem quotas and mount flags (read-only, noexec) on the temp volume.
- Run the process as a user with permission to create files in the temp directory.
Example fix
// before (unwritable default temp dir)
snap, err := os.CreateTemp("", "snapshot") // fails: open /tmp/snapshot...: read-only file system
// after
// launch with a writable temp dir, e.g. in the service unit/container:
// Environment=TMPDIR=/var/lib/myapp/tmp (and ensure the dir exists and is writable) Defensive patterns
Strategy: validation
Validate before calling
tmp := os.TempDir()
if fi, err := os.Stat(tmp); err != nil || !fi.IsDir() {
return fmt.Errorf("temp dir %s unavailable: %w", tmp, err)
}
probe, err := os.CreateTemp(tmp, "snapshot-probe")
if err != nil { return fmt.Errorf("cannot write temp files: %w", err) }
probe.Close(); os.Remove(probe.Name()) Prevention
- Ensure /tmp (or $TMPDIR) exists, is writable, and has free disk space in every deployment (Dockerfile: RUN mkdir -p /tmp).
- Avoid read-only root filesystems without a writable tmpfs mount.
- Monitor disk usage and inodes on the node.
- In tests or sandboxes, set TMPDIR explicitly to a known-writable directory.
When it happens
Trigger: Calling Restore (via snapshotRestore) when os.CreateTemp("", "snapshot") fails — e.g. the default temp directory (TMPDIR/tmp) does not exist, is not writable, the disk is full, or the process lacks permission to create files there.
Common situations: Containers launched with a read-only or unwritable /tmp; TMPDIR pointing at a nonexistent directory; disk-quota exhaustion on the node; running under a hardened security profile (noexec/no-temp files) or a stripped-down container image missing /tmp.
Related errors
- unable to read rooted allocation directory
- can't seek to offset %d: %w
- Couldn't copy %q to %q: %w
- error writing to file %q: %w
- failed to list entries: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/ccb7becedfacba44.
Report an issue: GitHub.