hashicorp/nomad · error

failed to rewind snapshot: %v

Error message

failed to rewind snapshot: %v

What it means

After syncing, writeSnapshot rewinds the temp archive with archive.Seek(0, 0) so the caller can stream it out (e.g. HTTP response). A Seek failure on the local temp file is unexpected and indicates the archive file descriptor is broken, so snapshot creation fails with this error.

Source

Thrown at helper/snapshot/snapshot.go:138

	compressor := gzip.NewWriter(out)

	// Write the archive.
	if err := write(compressor, metadata, snap); err != nil {
		return nil, fmt.Errorf("failed to write snapshot file: %v", err)
	}

	// Finish the compressed stream.
	if err := compressor.Close(); err != nil {
		return nil, fmt.Errorf("failed to compress snapshot file: %v", err)
	}

	// Sync the compressed file and rewind it so it's ready to be streamed
	// out by the caller.
	if err := archive.Sync(); err != nil {
		return nil, fmt.Errorf("failed to sync snapshot: %v", err)
	}
	if _, err := archive.Seek(0, 0); err != nil {
		return nil, fmt.Errorf("failed to rewind snapshot: %v", err)
	}

	checksum := "sha-256=" + base64.StdEncoding.EncodeToString(hash.Sum(nil))

	keep = true
	return &Snapshot{archive, metadata.Index, checksum}, nil
}

// Index returns the index of the snapshot. This is safe to call on a nil
// snapshot, it will just return 0.
func (s *Snapshot) Index() uint64 {
	if s == nil {
		return 0
	}
	return s.index
}

func (s *Snapshot) Checksum() string {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Ensure TMPDIR points to a regular local filesystem that supports seeking (not a pipe or procfs-like mount).
  2. Check the wrapped %v cause for the errno (e.g. EBADF/ESPIPE) and fix the underlying file/environment issue.
  3. Confirm no external cleanup (tmpwatch/tmpreaper) or code path closed the temp file mid-write.
  4. Retry snapshot creation after fixing the environment.

Example fix

// before: TMPDIR=/dev/shm-like or pipe-backed fs → ESPIPE
// after
export TMPDIR=/var/lib/myapp/tmp   # regular seekable filesystem
Defensive patterns

Strategy: validation

Validate before calling

// temp dir must be a regular, seekable filesystem
if fi, err := os.Stat(os.TempDir()); err != nil || !fi.IsDir() {
	return fmt.Errorf("invalid TMPDIR")
}

Try / catch

snap, err := snapshot.New(...)
if err != nil && strings.Contains(err.Error(), "failed to rewind snapshot") {
	logger.Error("cannot seek snapshot temp file; check TMPDIR/filesystem", "err", err)
	return err
}

Prevention

When it happens

Trigger: New or NewFromFSM where archive.Seek(0, 0) returns an error: the temp file was closed or replaced unexpectedly, the file descriptor is invalid (EBADF), or an exotic filesystem doesn't support seeking on the temp file.

Common situations: TMPDIR on a filesystem without seek support (pipes/special filesystems); custom TMPDIR misconfiguration; corrupted file descriptor after earlier I/O failures.

Related errors


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