hashicorp/nomad · error

failed to create snapshot file: %v

Error message

failed to create snapshot file: %v

What it means

writeSnapshot wraps os.CreateTemp failures when creating the temporary file that receives the snapshot archive. The library streams the snapshot to disk rather than buffering it in memory, so the very first step is creating this scratch file; if the OS cannot create it, snapshot creation (via New or NewFromFSM) aborts with this message. The temp file is normally deleted in Close() unless the snapshot succeeds.

Source

Thrown at helper/snapshot/snapshot.go:100

	}

	return writeSnapshot(logger, metadata, snap)
}

func writeSnapshot(logger hclog.Logger, metadata *raft.SnapshotMeta, snap io.ReadCloser) (*Snapshot, error) {

	defer func() {
		if err := snap.Close(); err != nil {
			logger.Error("Failed to close Raft snapshot", "error", err)
		}
	}()

	// Make a scratch file to receive the contents so that we don't buffer
	// everything in memory. This gets deleted in Close() since we keep it
	// around for re-reading.
	archive, err := os.CreateTemp("", "snapshot")
	if err != nil {
		return nil, fmt.Errorf("failed to create snapshot file: %v", err)
	}

	// If anything goes wrong after this point, we will attempt to clean up
	// the temp file. The happy path will disarm this.
	var keep bool
	defer func() {
		if keep {
			return
		}

		if err := os.Remove(archive.Name()); err != nil {
			logger.Error("Failed to clean up temp snapshot", "error", err)
		}
	}()

	hash := sha256.New()
	out := io.MultiWriter(hash, archive)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check disk space and inode availability on the temp filesystem (df -h /tmp, df -i).
  2. Verify the TMPDIR environment variable points to an existing, writable directory, or fix it to a valid path.
  3. Ensure the process runs with permission to create files in the temp directory (mount a writable volume in containers).
  4. If /tmp is noexec/read-only, set TMPDIR to a writable location such as the data directory before starting the process.

Example fix

// before: TMPDIR=/nonexistent ./app  →  failed to create snapshot file: open /nonexistent/...: no such file or directory
// after
export TMPDIR=/var/lib/myapp/tmp   # existing, writable directory
mkdir -p $TMPDIR && ./app
Defensive patterns

Strategy: validation

Validate before calling

func ensureTempWritable() error {
	d := os.TempDir()
	if st, err := os.Stat(d); err != nil || !st.IsDir() {
		return fmt.Errorf("temp dir %q missing: %v", d, err)
	}
	f, err := os.CreateTemp(d, "probe")
	if err != nil { return err }
	name := f.Name(); f.Close(); os.Remove(name)
	return nil
}

Try / catch

snap, err := snapshot.New(...) // or NewFromFSM
if err != nil && strings.Contains(err.Error(), "failed to create snapshot file") {
	logger.Error("snapshot temp file creation failed; check TMPDIR/disk", "err", err)
	return err
}

Prevention

When it happens

Trigger: Calling New or NewFromFSM when os.CreateTemp("", "snapshot") fails: no writable temp directory, TMPDIR pointing to a nonexistent or read-only path, disk full (no inodes/space), or sandboxed environments restricting /tmp access.

Common situations: Containers with a read-only root filesystem or tiny tmpfs; TMPDIR set to a path that doesn't exist; running under security profiles (seccomp/AppArmor) that block temp file creation; disk quota exhausted on the node.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/4b56c05ff46dcc40. Report an issue: GitHub.