hashicorp/packer · error

unable to create dir: %s

Error message

unable to create dir: %s

What it means

PostProcess-time failure in the checksum post-processor: before writing each checksum file it ensures the parent directory exists with os.MkdirAll; if that fails (permission denied, path is a file, read-only volume) the whole post-process aborts with keep=true. The wrapped OS error details the cause.

Source

Thrown at post-processor/checksum/post-processor.go:136

	newartifact := NewArtifact(artifact.Files())

	for _, ct := range p.config.ChecksumTypes {
		h = getHash(ct)
		generatedData["ChecksumType"] = ct
		p.config.ctx.Data = generatedData

		for _, art := range files {
			checksumFile, err := interpolate.Render(p.config.OutputPath, &p.config.ctx)
			if err != nil {
				return nil, false, true, err
			}

			if _, err := os.Stat(checksumFile); err != nil {
				newartifact.files = append(newartifact.files, checksumFile)
			}
			if err := os.MkdirAll(filepath.Dir(checksumFile), os.FileMode(0755)); err != nil {
				return nil, false, true, fmt.Errorf("unable to create dir: %s", err.Error())
			}
			fw, err := os.OpenFile(checksumFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(0644))
			if err != nil {
				return nil, false, true, fmt.Errorf("unable to create file %s: %s", checksumFile, err.Error())
			}
			fr, err := os.Open(art)
			if err != nil {
				fw.Close()
				return nil, false, true, fmt.Errorf("unable to open file %s: %s", art, err.Error())
			}

			if _, err = io.Copy(h, fr); err != nil {
				fr.Close()
				fw.Close()
				return nil, false, true, fmt.Errorf("unable to compute %s hash for %s", ct, art)
			}
			fr.Close()
			_, _ = fw.WriteString(fmt.Sprintf("%x\t%s\n", h.Sum(nil), filepath.Base(art)))

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Set `output` to a path under a writable directory you control (relative paths resolve under the working/output directory)
  2. Check ownership/permissions of the target's parent and pre-create the directory yourself
  3. Ensure no file exists at a path component where a directory is required
  4. Verify mount flags / security policies if running in a container

Example fix

// before
output = "/usr/local/share/packer/{{.BuildName}}.checksum"
// after
output = "out/{{.BuildName}}.checksum"
Defensive patterns

Strategy: validation

Validate before calling

// shell: pre-flight check that the output directory is creatable/writable
OUT="$(pwd)/out"
mkdir -p "$OUT" || { echo "cannot create $OUT"; exit 1; }
test -w "$OUT" || { echo "$OUT not writable"; exit 1; }
# also ensure no file occupies a path component:
while [ -f "$(dirname "$OUT")" ]; do echo "conflict"; exit 1; done

Try / catch

artifact, _, _, err := pp.PostProcess(ctx, ui, art)
if err != nil {
    if strings.Contains(err.Error(), "unable to create dir") {
        // fix permissions / path collision, rerun
    }
    return err
}

Prevention

When it happens

Trigger: The rendered output template resolves to a directory that cannot be created, e.g. output = "/etc/packer/out.checksum" (no permission), output under a read-only mount, or a path component exists as a regular file so MkdirAll returns ENOTDIR.

Common situations: Absolute paths pointing into protected system directories; output on a read-only container volume; existing FILE conflicting with an intended directory in the path; SELinux/AppArmor denials.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


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