hashicorp/packer · error
no stable Packer releases found in index at %s
Error message
no stable Packer releases found in index at %s
What it means
fetchLatestPackerVersion downloads the HashiCorp releases index (releases.hashicorp.com/packer/index.json), parses every version key with Masterminds/semver, and filters out any version carrying a prerelease suffix (alpha/beta/rc). If after that filtering no version remains, it throws this error because there is nothing to sort or select as the latest stable release. It is a guard against an empty/invalid index rather than a download failure — the HTTP fetch and JSON decode already succeeded.
Source
Thrown at provisioner/hcp-sbom/packer_release_fetch.go:91
err = json.NewDecoder(resp.Body).Decode(&indexData)
if err != nil {
return "", fmt.Errorf("failed to retrieve packer release index from %s: %w", indexURL, err)
}
var semverList []*semver.Version
for vStr := range indexData.Versions {
v, parseErr := semver.NewVersion(vStr)
if parseErr != nil {
continue
}
if v.Prerelease() != "" {
continue // skip alpha/beta/rc
}
semverList = append(semverList, v)
}
if len(semverList) == 0 {
return "", fmt.Errorf("no stable Packer releases found in index at %s", indexURL)
}
sort.Sort(semver.Collection(semverList))
latest := semverList[len(semverList)-1]
log.Printf("[INFO] Latest stable Packer version from releases index: %s", latest.Original())
return latest.Original(), nil
}
// downloadURLToTempFile downloads url into a new temp file and returns its path.
// On any error the temp file is removed. The caller owns the returned file on success.
func downloadURLToTempFile(ctx context.Context, client *http.Client, url, suffix string) (string, error) {
f, err := os.CreateTemp("", "packer-dl-*"+suffix)
if err != nil {
return "", fmt.Errorf("failed to create temp file: %w", err)
}
tmpPath := f.Name()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)View on GitHub (pinned to eb36e3c3e4)
Solutions
- Check that the releases index is reachable and real: curl https://releases.hashicorp.com/packer/index.json and confirm the versions map contains stable entries like "1.13.0".
- If using a proxy or mirror, ensure it caches the full index and does not strip stable versions or serve an empty/fixture document.
- If pointing the code at a custom index URL for testing, populate the fixture with at least one valid stable semver key (no prerelease suffix).
- Inspect the raw JSON for malformed version keys or unexpected structure and re-fetch; a corrupted cache should be purged.
- If only prereleases exist upstream, wait for the next stable release or pin/hardcode a known-good version instead of resolving from the index.
Example fix
// before: error surfaces only at runtime deep in the build
latest, err := fetchLatestPackerVersion(ctx, client)
// after: sanity-check the index yourself before relying on dynamic resolution
resp, _ := client.Get("https://releases.hashicorp.com/packer/index.json")
var idx releaseIndex
json.NewDecoder(resp.Body).Decode(&idx)
hasStable := false
for k := range idx.Versions {
if v, err := semver.NewVersion(k); err == nil && v.Prerelease() == "" {
hasStable = true
break
}
}
if !hasStable {
return errors.New("release index has no stable versions; pin Packer version explicitly")
} Defensive patterns
Strategy: validation
Validate before calling
// Check the release index yourself before invoking the fetch path
resp, err := http.Get("https://releases.hashicorp.com/packer/index.json")
if err != nil { return err }
var idx struct{ Versions map[string]json.RawMessage `json:"versions"` }
if err := json.NewDecoder(resp.Body).Decode(&idx); err != nil { return err }
resp.Body.Close()
hasStable := false
for k := range idx.Versions {
if v, err := semver.NewVersion(k); err == nil && v.Prerelease() == "" {
hasStable = true
break
}
}
if !hasStable {
return fmt.Errorf("release index has no stable Packer versions; pin a version instead")
} Type guard
// Ensure a parsed version is usable as the latest stable release
func isStableVersion(k string) bool {
v, err := semver.NewVersion(k)
return err == nil && v.Prerelease() == ""
} Prevention
- Sanity-check custom/mirrored index URLs with curl before wiring them into builds.
- Pin a Packer version in CI when you cannot tolerate upstream index anomalies.
- Alert on index.json contents in monitoring so an empty/stale mirror is caught early.
- Keep TMPDIR/network healthy so you never fall back to untrusted mirrors.
- Log the full version list at debug level to make empty-filter regressions obvious.
When it happens
Trigger: The index JSON decoded successfully but its 'versions' map is empty, contains only keys that semver.NewVersion cannot parse (malformed keys), or contains only prerelease versions (all keys have a -alpha/-beta/-rc suffix) so every candidate is skipped by the 'skip alpha/beta/rc' filter.
Common situations: A proxy, mirror, or corporate artifact store serves a truncated, stale, or rewritten index.json (e.g. only 1.11.0-dev entries cached); the base URL is overridden to a mock/fixture with an empty versions map; HashiCorp publishes only prerelease builds to the index; a malicious or corrupted index contains garbage version keys.
Related errors
- invalid self-reported version %q: %s
- index.json contains no usable versions
- source must be specified when auto_generate is not enabled
- Only one of script or scripts can be specified.
- Must supply an 'elevated_user' if 'elevated_password' provid
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/c79f5b11c7918950.
Report an issue: GitHub.