hashicorp/packer · error
failed to close temp file: %w
Error message
failed to close temp file: %w
What it means
downloadURLToTempFile buffers the downloaded Packer release zip into an os.CreateTemp file and closes it after io.Copy. This error wraps any *os.PathError returned by f.Close(), meaning the final flush/sync of buffered data to disk (or the file-descriptor release) failed. Because the close already failed, the temp file is deleted and the caller must retry; a partial or corrupt file is never returned.
Source
Thrown at provisioner/hcp-sbom/packer_release_fetch.go:138
return "", fmt.Errorf("HTTP request failed: %w", err)
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
_ = f.Close()
_ = os.Remove(tmpPath)
return "", fmt.Errorf("HTTP %d for %s", resp.StatusCode, url)
}
_, copyErr := io.Copy(f, resp.Body)
closeErr := f.Close()
if copyErr != nil {
_ = os.Remove(tmpPath)
return "", fmt.Errorf("failed to write download: %w", copyErr)
}
if closeErr != nil {
_ = os.Remove(tmpPath)
return "", fmt.Errorf("failed to close temp file: %w", closeErr)
}
return tmpPath, nil
}
// downloadChecksumFile fetches the SHA256SUMS text file at url.
func downloadChecksumFile(ctx context.Context, client *http.Client, url string) (string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return "", fmt.Errorf("failed to build request for %s: %w", url, err)
}
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("failed to download %s: %w", url, err)
}
defer func() { _ = resp.Body.Close() }()
View on GitHub (pinned to eb36e3c3e4)
Solutions
- Check free space on the filesystem backing os.TempDir() (df -h /tmp) and free space or point TMPDIR to a volume with room for the Packer zip
- Set the TMPDIR environment variable to a larger volume and rerun the hcp-sbom provisioning step
- Check dmesg / container runtime logs for I/O errors or ephemeral-storage limits and fix the underlying disk or raise the quota
- Retry the operation — the code already removed the bad temp file, and downloadPackerRelease wraps this in a retry.Config with 3 tries
Example fix
// before: trusting tmpfs default // (download fails with "failed to close temp file: ... no space left on device") // after: point temp files at a larger volume before running packer // $ export TMPDIR=/var/tmp # volume with adequate free space // TMPDIR=/var/tmp packer build template.pkr.hcl
Defensive patterns
Strategy: validation
Validate before calling
// before triggering the download flow, ensure the temp volume has room for the zip
const minFreeBytes = 200 << 20 // Packer zip is ~25-150MB; keep headroom
var st syscall.Statfs_t
if err := syscall.Statfs(os.TempDir(), &st); err != nil {
return fmt.Errorf("cannot stat temp dir %s: %w", os.TempDir(), err)
}
free := uint64(st.Bavail) * uint64(st.Bsize)
if free < minFreeBytes {
return fmt.Errorf("only %d bytes free in %s; set TMPDIR to a larger volume", free, os.TempDir())
} Type guard
// ensure the wrapped cause is a filesystem (PathError) problem you can act on
func asPathError(err error) (*fs.PathError, bool) {
var pe *fs.PathError
if errors.As(err, &pe) {
return pe, true
}
return nil, false
}
// usage: if pe, ok := asPathError(err); ok && errors.Is(pe.Err, syscall.ENOSPC) { ... } Prevention
- Monitor free space on the filesystem backing os.TempDir() before long builds
- Point TMPDIR at a dedicated volume with headroom for ~150MB downloads
- Raise container ephemeral-storage limits when running Packer in Kubernetes/CI containers
- Watch dmesg for disk I/O errors on build hosts
- Rely on the built-in 3-try retry in downloadPackerRelease for transient close failures
When it happens
Trigger: f.Close() returns a non-nil error after a successful io.Copy from the HTTP response body — typically ENOSPC (disk full), EIO (disk/device error), or an fsync-level failure while flushing written bytes in downloadURLToTempFile (packer_release_fetch.go:131-138).
Common situations: The disk or tmpfs backing os.TempDir() (e.g. /tmp) is full or nearly full after streaming a large zip; the container/pod ephemeral storage quota is exhausted; underlying storage encountered I/O errors; or a filesystem was unmounted/remounted mid-download.
Related errors
- failed to close temporary file for Packer SBOM %s: %s
- failed to open Packer SBOM file %q: %s
- failed to write SBOM to %q: %s
- failed to get source: %w
- could not create plugin folder %q: %w
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/ad95c040380bed42.
Report an issue: GitHub.