hashicorp/packer · error

failed to create output file %q: %s

Error message

failed to create output file %q: %s

What it means

This error is returned by processSBOMForHCP when os.Create fails to create/truncate the internal Packer SBOM output file at the destination path taken from generatedData["dst"]. It means the provisioner could not open a writable file at that path on the machine running Packer (the host, not the build VM). The wrapped OS error (e.g. permission denied, no such file or directory) is embedded in the message.

Source

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

// processSBOMForHCP validates, compresses, and prepares SBOM for HCP upload
func (p *Provisioner) processSBOMForHCP(generatedData map[string]interface{}, sbomData []byte) error {
	// Validate SBOM format
	format, err := validateSBOM(sbomData)
	if err != nil {
		return fmt.Errorf("SBOM validation failed: %s", err)
	}

	// Get destination path from generatedData
	pkrDst, ok := generatedData["dst"].(string)
	if !ok || pkrDst == "" {
		return fmt.Errorf("packer destination path missing from configs: this is an internal error")
	}

	// Write PackerSBOM to destination
	outFile, err := os.Create(pkrDst)
	if err != nil {
		return fmt.Errorf("failed to create output file %q: %s", pkrDst, err)
	}
	defer func() {
		_ = outFile.Close() // Cleanup, ignore error
	}()

	err = json.NewEncoder(outFile).Encode(PackerSBOM{
		RawSBOM: sbomData,
		Format:  format,
		Name:    p.config.SbomName,
	})
	if err != nil {
		return fmt.Errorf("failed to write SBOM to %q: %s", pkrDst, err)
	}

	// Also save to user destination if specified
	if p.config.Destination != "" {
		usrDst, err := p.getUserDestination()
		if err != nil {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Read the wrapped OS error in the message to identify the cause (permission denied vs no such file or directory).
  2. Ensure the parent directory of the destination path exists: mkdir -p $(dirname <pkrDst>).
  3. Verify the user running Packer has write permission to that directory, or run Packer with sufficient privileges.
  4. Check that dst is not a directory and is on a writable filesystem (e.g. not a read-only container rootfs).
  5. Re-run the build; this error occurs before upload, so nothing was uploaded to HCP.

Example fix

// before (shell): run packer with dst under a dir the user cannot write
$ packer build template.pkr.hcl
// after
$ sudo mkdir -p /packer/sbom && sudo chown $(whoami) /packer/sbom
$ packer build template.pkr.hcl
Defensive patterns

Strategy: validation

Validate before calling

pkrDst, ok := generatedData["dst"].(string)
if !ok || pkrDst == "" {
	return fmt.Errorf("destination path missing")
}
if st, err := os.Stat(filepath.Dir(pkrDst)); err != nil || !st.IsDir() {
	return fmt.Errorf("destination directory %q not usable: %w", filepath.Dir(pkrDst), err)
}

Type guard

func dstOK(generatedData map[string]interface{}) (string, bool) {
	s, ok := generatedData["dst"].(string)
	return s, ok && s != ""
}

Prevention

When it happens

Trigger: processSBOMForHCP is called (via provisionWithExistingSBOM or provisionWithNativeGeneration) after a valid SBOM is obtained, and os.Create(pkrDst) fails because the dst directory does not exist, the path is not writable by the Packer process, dst points to a read-only filesystem, or dst is a directory.

Common situations: Running Packer as a non-root user while dst resolves to a root-owned path (e.g. /packer/...); HCP artifact storage path not present on the host; dst configured via template variables that expand to an invalid or empty-but-truthy path; containerized Packer with a read-only rootfs.

Related errors


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