hashicorp/packer · error

Unable to create archive %s: %s

Error message

Unable to create archive %s: %s

What it means

After ensuring the directory exists, PostProcess creates the archive file with os.Create. This error means the OS refused to create/truncate the target archive file itself — permission denied, path is a directory, no space, or an unwritable filesystem.

Source

Thrown at post-processor/compress/post-processor.go:149

	generatedData["BuilderType"] = p.config.PackerBuilderType
	p.config.ctx.Data = generatedData

	target, err := interpolate.Render(p.config.OutputPath, &p.config.ctx)
	if err != nil {
		return nil, false, false, fmt.Errorf("Error interpolating output value: %s", err)
	} else {
		fmt.Println(target)
	}

	newArtifact := &Artifact{Path: target}

	if err = os.MkdirAll(filepath.Dir(target), os.FileMode(0755)); err != nil {
		return nil, false, false, fmt.Errorf(
			"Unable to create dir for archive %s: %s", target, err)
	}
	outputFile, err := os.Create(target)
	if err != nil {
		return nil, false, false, fmt.Errorf(
			"Unable to create archive %s: %s", target, err)
	}
	defer outputFile.Close()

	// Setup output interface. If we're using compression, output is a
	// compression writer. Otherwise it's just a file.
	var output io.WriteCloser
	errTmpl := "error creating %s writer: %s"
	switch p.config.Algorithm {
	case "bgzf":
		ui.Say(fmt.Sprintf("Using bgzf compression with %d cores for %s",
			runtime.GOMAXPROCS(-1), target))
		output, err = makeBGZFWriter(outputFile, p.config.CompressionLevel)
		if err != nil {
			return nil, false, false, fmt.Errorf(errTmpl, p.config.Algorithm, err)
		}
		defer output.Close()
	case "bzip2":

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Check disk space (df -h) and free space if full
  2. Verify the target path is not an existing directory and the filename is valid
  3. Ensure the user running packer can write to the target directory (ls -ld)
  4. Point output_path to a writable location

Example fix

// before: collides with a directory named artifact.tar.gz
output = "./output/artifact.tar.gz"
// after
output = "./output/artifact-{{timestamp}}.tar.gz"
Defensive patterns

Strategy: validation

Validate before calling

if fi, err := os.Stat(target); err == nil && fi.IsDir() {
    return fmt.Errorf("%s is a directory", target)
}
// also check writability and free space
if err := unix.Access(filepath.Dir(target), unix.W_OK); err != nil { /* ... */ }

Try / catch

if err != nil {
    switch {
    case errors.Is(err, fs.ErrExist):
        // target exists as dir or file: choose a unique name
    case errors.Is(err, fs.ErrPermission):
        // fall back to another output location
    default:
        // check disk full (ENOSPC)
    }
}

Prevention

When it happens

Trigger: os.Create(target) fails during PostProcess: target exists as a directory, the directory lacks write permission, the filesystem is full or read-only, or the name is invalid for the OS.

Common situations: output_path resolving to an existing directory name; disk full after long builds; output dir mounted read-only; filename with characters invalid on the host OS; stale file owned by another user.

Related errors


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