hashicorp/packer · error

failed to create temporary file in user SBOM directory %s: %

Error message

failed to create temporary file in user SBOM directory %s: %s

What it means

When the user-specified SBOM destination already exists and is a directory, getUserDestination tries to create a uniquely named temporary file (`packer-user-sbom-*.json`) inside it via os.CreateTemp. If that creation fails (permissions, read-only filesystem, disk full, dst not actually writable), the provisioner returns this error wrapping the underlying os error. It runs on the host running Packer, before uploading or writing the SBOM.

Source

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

	// Store in generatedData for potential reuse
	generatedData["OSType"] = osType
	generatedData["OSArch"] = osArch

	return osType, osArch, nil
}

// getUserDestination determines and returns the destination path for the user SBOM file.
func (p *Provisioner) getUserDestination() (string, error) {
	dst := p.config.Destination

	// Check if the destination exists and determine its type
	info, err := os.Stat(dst)
	if err == nil {
		if info.IsDir() {
			// If the destination is a directory, create a temporary file inside it
			tmpFile, err := os.CreateTemp(dst, "packer-user-sbom-*.json")
			if err != nil {
				return "", fmt.Errorf("failed to create temporary file in user SBOM directory %s: %s", dst, err)
			}
			dst = tmpFile.Name()
			_ = tmpFile.Close() // Ignore error on close after getting name
		}
		return dst, nil
	}

	outDir := filepath.Dir(dst)
	// In case the destination does not exist, we'll get the dirpath,
	// and create it if it doesn't already exist
	err = os.MkdirAll(outDir, 0755)
	if err != nil {
		return "", fmt.Errorf("failed to create destination directory for user SBOM: %s", err)
	}

	// Check if the destination is a directory after the previous step.
	//
	// This happens if the path specified ends with a `/`, in which case the

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. chmod/chown the destination directory so the user running `packer build` can create files in it.
  2. Point `destination` at a writable location (e.g. `~/sboms/`, `/tmp`, or the build output directory) instead of a protected system directory.
  3. Check disk space with `df -h` on the destination's filesystem and free space if full.
  4. If the directory must stay read-only, pass a full file path (not a directory) as `destination` so no temp file needs to be created.
  5. Verify no immutable flag (chattr +i) or mount option (ro) is set: `lsattr`, `mount | grep <path>`.

Example fix

// before (packer template)
destination = "/usr/share/sboms/"  // root-owned, not writable

// after
destination = "{{user `home`}}/sboms/"
Defensive patterns

Strategy: validation

Validate before calling

// Check writability of the destination directory before running packer build:
dst="$HOME/sboms"
mkdir -p "$dst"
touch "$dst/.writetest" && rm "$dst/.writetest" || { echo "$dst not writable"; exit 1; }

Try / catch

// If embedding the provisioner in Go:
dst, err := p.getUserDestination()
if err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) && errors.Is(perr.Err, syscall.EACCES) {
        return fmt.Errorf("destination %s not writable: run as a user with write access", perr.Path)
    }
    return err
}

Prevention

When it happens

Trigger: Config `destination` points to an existing directory, and os.CreateTemp(dst, ...) fails because the directory is not writable by the Packer process, is read-only (ro bind mount, immutable, full disk), or dst is a path like a symlink to an unwritable location.

Common situations: Pointing destination at /usr/share, /etc, or another root-owned directory while running Packer unprivileged; running Packer in a container with a read-only volume mounted at the destination; destination on a full tmpfs; macOS sandboxed FS access denying writes to the chosen folder.

Related errors


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