hashicorp/packer · error
packer binary %q not found in release zip %s
Error message
packer binary %q not found in release zip %s
What it means
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.
Source
Thrown at provisioner/hcp-sbom/packer_release_fetch.go:288
if goos == "windows" {
binaryName = "packer.exe"
}
zr, err := zip.OpenReader(candidateZipPath)
if err != nil {
return fmt.Errorf("failed to open downloaded zip: %w", err)
}
defer func() { _ = zr.Close() }()
foundBinary := false
for _, f := range zr.File {
if f.Name == binaryName {
foundBinary = true
break
}
}
if !foundBinary {
return fmt.Errorf("packer binary %q not found in release zip %s", binaryName, zipURL)
}
keepCandidate = true
zipPath = candidateZipPath
return nil
})
if err != nil {
return "", fmt.Errorf("failed to download and verify Packer release zip: %w", err)
}
log.Printf("[INFO] Downloaded and verified Packer release zip: %s", zipPath)
return zipPath, nil
}
View on GitHub (pinned to eb36e3c3e4)
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.
Example fix
// resilient lookup if layout changes upstream
foundBinary := false
for _, f := range zr.File {
if f.Name == binaryName || strings.HasSuffix(f.Name, "/"+binaryName) {
foundBinary = true
break
}
} Defensive patterns
Strategy: type-guard
Validate before calling
zr, err := zip.OpenReader(zipPath)
if err != nil {
return err
}
defer zr.Close()
binaryName := "packer"
if goos == "windows" {
binaryName = "packer.exe"
}
found := false
for _, f := range zr.File {
if f.Name == binaryName || strings.HasSuffix(f.Name, "/"+binaryName) {
found = true
break
}
}
if !found {
return fmt.Errorf("unexpected archive layout: %s missing from %s", binaryName, zipPath)
} Type guard
func hasRootBinary(zr *zip.ReadCloser, name string) bool {
for _, f := range zr.File {
if f.Name == name {
return true
}
}
return false
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Error creating zip: %s
- Failed to add zip header for %s: %s
- failed to open downloaded zip: %w
- extract file: %w
- Error creating tar: %s
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/095ab1403bdd274a.
Report an issue: GitHub.