{"record":{"id":"12497d4796bcc04f","repo":"hashicorp/packer","slug":"failed-to-create-temporary-file-in-user-sbom-direc","errorCode":null,"errorMessage":"failed to create temporary file in user SBOM directory %s: %s","messagePattern":"failed to create temporary file in user SBOM directory (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"provisioner/hcp-sbom/provisioner.go","lineNumber":435,"sourceCode":"\t// Store in generatedData for potential reuse\n\tgeneratedData[\"OSType\"] = osType\n\tgeneratedData[\"OSArch\"] = osArch\n\n\treturn osType, osArch, nil\n}\n\n// getUserDestination determines and returns the destination path for the user SBOM file.\nfunc (p *Provisioner) getUserDestination() (string, error) {\n\tdst := p.config.Destination\n\n\t// Check if the destination exists and determine its type\n\tinfo, err := os.Stat(dst)\n\tif err == nil {\n\t\tif info.IsDir() {\n\t\t\t// If the destination is a directory, create a temporary file inside it\n\t\t\ttmpFile, err := os.CreateTemp(dst, \"packer-user-sbom-*.json\")\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to create temporary file in user SBOM directory %s: %s\", dst, err)\n\t\t\t}\n\t\t\tdst = tmpFile.Name()\n\t\t\t_ = tmpFile.Close() // Ignore error on close after getting name\n\t\t}\n\t\treturn dst, nil\n\t}\n\n\toutDir := filepath.Dir(dst)\n\t// In case the destination does not exist, we'll get the dirpath,\n\t// and create it if it doesn't already exist\n\terr = os.MkdirAll(outDir, 0755)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create destination directory for user SBOM: %s\", err)\n\t}\n\n\t// Check if the destination is a directory after the previous step.\n\t//\n\t// This happens if the path specified ends with a `/`, in which case the","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/provisioner/hcp-sbom/provisioner.go#L417-L453","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["chmod/chown the destination directory so the user running `packer build` can create files in it.","Point `destination` at a writable location (e.g. `~/sboms/`, `/tmp`, or the build output directory) instead of a protected system directory.","Check disk space with `df -h` on the destination's filesystem and free space if full.","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.","Verify no immutable flag (chattr +i) or mount option (ro) is set: `lsattr`, `mount | grep <path>`."],"exampleFix":"// before (packer template)\ndestination = \"/usr/share/sboms/\"  // root-owned, not writable\n\n// after\ndestination = \"{{user `home`}}/sboms/\"","handlingStrategy":"validation","validationCode":"// Check writability of the destination directory before running packer build:\ndst=\"$HOME/sboms\"\nmkdir -p \"$dst\"\ntouch \"$dst/.writetest\" && rm \"$dst/.writetest\" || { echo \"$dst not writable\"; exit 1; }","typeGuard":null,"tryCatchPattern":"// If embedding the provisioner in Go:\ndst, err := p.getUserDestination()\nif err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) && errors.Is(perr.Err, syscall.EACCES) {\n        return fmt.Errorf(\"destination %s not writable: run as a user with write access\", perr.Path)\n    }\n    return err\n}","preventionTips":["Point `destination` at a user-writable directory ($HOME, project dir, output_directory)","Never target system dirs like /usr/share or /etc unless running as root","In containers, mount the output volume rw and not read-only","Monitor disk space on the destination filesystem in CI","Pass a full file path instead of a trailing-slash directory when possible"],"tags":["filesystem","permissions","provisioner","temp-file"],"backgroundTag":"temp-file-creation-failed","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}