hashicorp/packer · error

downloaded SBOM is empty

Error message

downloaded SBOM is empty

What it means

Returned by downloadSBOM (provisioner/hcp-sbom/provisioner.go:836) when the communicator reports a successful download but the received buffer is zero bytes. Packer treats an empty SBOM as invalid because validation and HCP upload cannot proceed with no content — usually the remote file was empty or truncated.

Source

Thrown at provisioner/hcp-sbom/provisioner.go:836

		return true
	default:
		return false
	}
}

// downloadSBOM downloads the SBOM file from the remote host
func (p *Provisioner) downloadSBOM(ctx context.Context, ui packersdk.Ui,
	comm packersdk.Communicator, remotePath string) ([]byte, error) {

	var buf bytes.Buffer
	log.Printf("Downloading SBOM from %s...", remotePath)

	if err := comm.Download(remotePath, &buf); err != nil {
		return nil, fmt.Errorf("failed to download SBOM: %s", err)
	}

	if buf.Len() == 0 {
		return nil, fmt.Errorf("downloaded SBOM is empty")
	}

	log.Printf("Downloaded SBOM (%d bytes)", buf.Len())
	return buf.Bytes(), nil
}

// cleanupRemoteFile removes a file from the remote host.
func (p *Provisioner) cleanupRemoteFile(ctx context.Context, ui packersdk.Ui,
	comm packersdk.Communicator, remotePath string) {

	if remotePath == "" {
		return
	}

	log.Printf("Cleaning up remote file: %s", remotePath)

	// Determine delete command based on path (Windows vs Unix)
	var cmdStr string

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Check scanner stderr lines in the build log — an empty stdout usually means the tool errored after the redirect opened the file.
  2. Verify scanner_args actually generate output (no --help/--version/--quiet flags) and match the bundled scanner version's CLI.
  3. Test the exact execute_command on a similar guest manually and confirm /tmp/packer-sbom.json is non-empty.
  4. Ensure the guest filesystem has free space and the scan path contains content to scan.
  5. Remove custom output-file flags so the only sink is the `> {{.Output}}` redirect.

Example fix

// before: scanner writes to its own file, stdout stays empty
scanner_args = ["--output", "/tmp/other.json"]
// after: let the provisioner's redirect capture the SBOM
scanner_args = []
Defensive patterns

Strategy: validation

Validate before calling

// After download, before processing:
if buf.Len() == 0 {
    // treat as generation failure: check scanner stderr before proceeding
}

Try / catch

data, err := p.downloadSBOM(ctx, ui, comm, remoteSBOMPath)
if err != nil {
    if strings.Contains(err.Error(), "empty") { /* scanner produced no output: check stderr */ }
    return err
}

Prevention

When it happens

Trigger: The remote SBOM file exists but is 0 bytes: the scanner command redirected output to {{.Output}} but the generation produced nothing (tool failed silently, wrong args like a quiet flag), or the scanner wrote to stderr while stdout (redirected) stayed empty.

Common situations: execute_command redirecting stdout but scanner writing the SBOM to a file of its own choosing (double-output confusion); scanner crashing after opening the output file; disk-full on guest leaving a 0-byte file; scanner_args containing a version/help flag that prints to stderr and writes no SBOM.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/2138ea3a70b5c9ac. Report an issue: GitHub.