{"record":{"id":"8b8e6004cd9bc28f","repo":"hashicorp/nomad","slug":"unexpected-file-q-in-snapshot","errorCode":null,"errorMessage":"unexpected file %q in snapshot","messagePattern":"unexpected file %q in snapshot","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/snapshot/archive.go","lineNumber":226,"sourceCode":"\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to read snapshot metadata: %v\", err)\n\t\t\t}\n\t\t\tif err := json.Unmarshal(buf, &metadata); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to decode snapshot metadata: %v\", err)\n\t\t\t}\n\n\t\tcase \"state.bin\":\n\t\t\tif _, err := io.Copy(io.MultiWriter(snap, snapHash), archive); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to read or write snapshot data: %v\", err)\n\t\t\t}\n\n\t\tcase \"SHA256SUMS\":\n\t\t\tif _, err := io.Copy(&shaBuffer, archive); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to read snapshot hashes: %v\", err)\n\t\t\t}\n\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unexpected file %q in snapshot\", hdr.Name)\n\t\t}\n\t}\n\n\t// Verify all the hashes.\n\tif err := hl.DecodeAndVerify(&shaBuffer); err != nil {\n\t\treturn fmt.Errorf(\"failed checking integrity of snapshot: %v\", err)\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":208,"sourceCodeEnd":237,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/snapshot/archive.go#L208-L237","documentation":"The snapshot archive is expected to contain exactly three tar entries: meta.json, state.bin, and SHA256SUMS. This error is thrown when the tar reader encounters any other file name, meaning the archive does not match the internal snapshot format. It indicates the input is not a Nomad snapshot produced by this library (or was tampered with/repacked).","triggerScenarios":"Calling snapshot.Verify/CopySnapshot/Restore on a tar archive that contains extra or differently-named members, e.g. a directory entry, OS metadata files like ._meta.json or PAX/global headers with odd names, or a user-made tarball that is not a real snapshot.","commonSituations":"Users hand-crafting or re-tarring snapshots; macOS-created archives containing AppleDouble files; restoring the wrong file (e.g. a config backup tarball) via nomad operator snapshot restore; archives round-tripped through tools that inject extra entries.","solutions":["Confirm the input file is a genuine Nomad snapshot (gzip'd tar with exactly meta.json, state.bin, SHA256SUMS) using tar -tzf; if not, obtain a real snapshot from the leader.","Inspect the archive listing for spurious entries (directories, ._* files) and rebuild the archive removing them if a hand-edit is unavoidable.","Check Nomad version compatibility: restore snapshots with the same or newer nomad operator snapshot restore tooling than the cluster that created them.","Re-take the snapshot via nomad operator snapshot save rather than manually assembling archives."],"exampleFix":"// before: piping an arbitrary tarball into Restore\nsnapshot.Restore(logger, backupTarball, r) // \"unexpected file \\\"./\\\" in snapshot\"\n\n// after: validate the snapshot before restoring\nif _, err := snapshot.Verify(snapshotFile); err != nil {\n    return fmt.Errorf(\"not a valid Nomad snapshot: %w\", err)\n}\nsnapshot.Restore(logger, snapshotFile, r)","handlingStrategy":"validation","validationCode":"// Ensure the input is a genuine Nomad snapshot before restoring\nfunc isNomadSnapshot(in io.Reader) bool {\n    if _, err := snapshot.Verify(in); err != nil {\n        return false\n    }\n    if s, ok := in.(io.Seeker); ok {\n        s.Seek(0, 0)\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only feed archives produced by nomad operator snapshot save (or snapshot.New) into Restore/CopySnapshot.","Never hand-edit or re-tar snapshot archives; treat them as opaque blobs.","On macOS, avoid archives created by naive tar of directories that can add AppleDouble entries."],"tags":["go","snapshot","format","validation"],"backgroundTag":"invalid-archive-format","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}