{"record":{"id":"095ab1403bdd274a","repo":"hashicorp/packer","slug":"packer-binary-q-not-found-in-release-zip-s","errorCode":null,"errorMessage":"packer binary %q not found in release zip %s","messagePattern":"packer binary %q not found in release zip (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"provisioner/hcp-sbom/packer_release_fetch.go","lineNumber":288,"sourceCode":"\t\tif goos == \"windows\" {\n\t\t\tbinaryName = \"packer.exe\"\n\t\t}\n\n\t\tzr, err := zip.OpenReader(candidateZipPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to open downloaded zip: %w\", err)\n\t\t}\n\t\tdefer func() { _ = zr.Close() }()\n\n\t\tfoundBinary := false\n\t\tfor _, f := range zr.File {\n\t\t\tif f.Name == binaryName {\n\t\t\t\tfoundBinary = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !foundBinary {\n\t\t\treturn fmt.Errorf(\"packer binary %q not found in release zip %s\", binaryName, zipURL)\n\t\t}\n\n\t\tkeepCandidate = true\n\t\tzipPath = candidateZipPath\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to download and verify Packer release zip: %w\", err)\n\t}\n\n\tlog.Printf(\"[INFO] Downloaded and verified Packer release zip: %s\", zipPath)\n\treturn zipPath, nil\n}\n","sourceCodeStart":270,"sourceCodeEnd":302,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/provisioner/hcp-sbom/packer_release_fetch.go#L270-L302","documentation":"Raised when the downloaded release zip opens fine but contains no entry exactly named 'packer' (or 'packer.exe' on Windows). The provisioner requires the bare binary at the zip root before accepting the artifact; anything else means the archive layout is not what upstream publishes.","triggerScenarios":"After iterating zr.File, no entry has f.Name == binaryName ('packer' or 'packer.exe'), so foundBinary stays false and the error is returned with the zipURL.","commonSituations":"Upstream changed the archive layout (binary nested under a subdirectory or renamed); a mirror/cache served a repackaged zip; wrong GOOS value causing expectations to diverge; a corrupted-but-valid zip containing junk.","solutions":["List the zip contents (unzip -l) and compare against the official release layout.","Confirm the binary name expectation ('packer' vs 'packer.exe') matches the actual archive for that GOOS.","If upstream changed packaging, update the provisioner to a version aware of the new layout.","Re-download from releases.hashicorp.com directly, avoiding mirrors/caches."],"exampleFix":"// resilient lookup if layout changes upstream\nfoundBinary := false\nfor _, f := range zr.File {\n\tif f.Name == binaryName || strings.HasSuffix(f.Name, \"/\"+binaryName) {\n\t\tfoundBinary = true\n\t\tbreak\n\t}\n}","handlingStrategy":"type-guard","validationCode":"zr, err := zip.OpenReader(zipPath)\nif err != nil {\n\treturn err\n}\ndefer zr.Close()\nbinaryName := \"packer\"\nif goos == \"windows\" {\n\tbinaryName = \"packer.exe\"\n}\nfound := false\nfor _, f := range zr.File {\n\tif f.Name == binaryName || strings.HasSuffix(f.Name, \"/\"+binaryName) {\n\t\tfound = true\n\t\tbreak\n\t}\n}\nif !found {\n\treturn fmt.Errorf(\"unexpected archive layout: %s missing from %s\", binaryName, zipPath)\n}","typeGuard":"func hasRootBinary(zr *zip.ReadCloser, name string) bool {\n\tfor _, f := range zr.File {\n\t\tif f.Name == name {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}","tryCatchPattern":null,"preventionTips":["unzip -l the official release once to know the expected layout","Avoid mirrors/repackaged zips; download from releases.hashicorp.com only","Update tooling when upstream changes packaging","Compare suspect archives against a known-good download"],"tags":["zip","archive","release-artifacts"],"backgroundTag":"binary-missing-in-archive","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}