hashicorp/nomad · error

file missing for %q

Error message

file missing for %q

What it means

After iterating all archive entries, DecodeAndVerify checks that every file that had a hash in the SHA256SUMS listing was actually seen in the archive. This error means an expected entry (meta.json, state.bin, or SHA256SUMS itself) is absent from the tar. It guards against incomplete or truncated archives.

Source

Thrown at helper/snapshot/archive.go:92

		}

		h, ok := hl.hashes[file]
		if !ok {
			return fmt.Errorf("list missing hash for %q", file)
		}
		if !bytes.Equal(sha, h.Sum([]byte{})) {
			return fmt.Errorf("hash check failed for %q", file)
		}
		seen[file] = struct{}{}
	}
	if err := s.Err(); err != nil {
		return err
	}

	// Make sure everything we had a hash for was seen.
	for file := range hl.hashes {
		if _, ok := seen[file]; !ok {
			return fmt.Errorf("file missing for %q", file)
		}
	}

	return nil
}

// write takes a writer and creates an archive with the snapshot metadata,
// the snapshot itself, and adds some integrity checking information.
func write(out io.Writer, metadata *raft.SnapshotMeta, snap io.Reader) error {
	// Start a new tarball.
	now := time.Now()
	archive := tar.NewWriter(out)

	// Create a hash list that we will use to write a SHA256SUMS file into
	// the archive.
	hl := newHashList()

	// Encode the snapshot metadata, which we need to feed back during a

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Recreate the snapshot with write() to regenerate all three entries (meta.json, state.bin, SHA256SUMS)
  2. Inspect the archive listing (tar -tf) to confirm which entry is missing
  3. Ensure no entry Size overrides consumed subsequent headers
  4. Restore from a known-good backup of the snapshot
Defensive patterns

Strategy: validation

Validate before calling

names, err := tarEntryNames(snapshotPath)
if err != nil {
    return err
}
for _, want := range []string{"meta.json", "state.bin", "SHA256SUMS"} {
    if !slices.Contains(names, want) {
        return fmt.Errorf("snapshot missing %s", want)
    }
}

Try / catch

if err := snapshot.DecodeAndVerify(w, r, size); err != nil {
    if strings.Contains(err.Error(), "file missing for") {
        return fmt.Errorf("incomplete snapshot: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: The tar writer failed to emit an entry, an entry was removed from the archive, or an entry's mis-set Size swallowed the next entry so it never appears as a separate tar header.

Common situations: A partially written snapshot (crash mid-write), manual extraction/repacking that dropped meta.json, or a corrupted tar stream where sizes drifted and headers were consumed as data.

Related errors


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