hashicorp/packer · error

create output dir %q: %w

Error message

create output dir %q: %w

What it means

outputPaths could not create (or create the parents of) the base directory where provenance/SBOM outputs will be written, using os.MkdirAll with mode 0755. The wrapped OS error carries the real reason.

Source

Thrown at post-processor/provenance/post-processor.go:640

func redactSensitiveVariables(userVariables map[string]string, sensitiveKeys []string) {
	for _, key := range sensitiveKeys {
		if _, ok := userVariables[key]; ok {
			userVariables[key] = redactedSensitiveValue
		}
	}
}

func (p *PostProcessor) outputPaths(source packersdk.Artifact) (outputPaths, error) {
	baseDir := p.config.OutputDir
	if baseDir == "" && len(source.Files()) > 0 {
		baseDir = filepath.Dir(source.Files()[0])
	}
	if baseDir == "" {
		baseDir = "."
	}

	if err := os.MkdirAll(baseDir, 0755); err != nil {
		return outputPaths{}, fmt.Errorf("create output dir %q: %w", baseDir, err)
	}

	name := p.outputStem(source)
	sbomFormat := internalsbom.FormatCycloneDX
	if parsed, err := internalsbom.ParseFormatFromArgs(p.config.SBOMFormat); err == nil {
		sbomFormat = parsed
	}
	sbomRaw := filepath.Join(baseDir, name+".sbom.cdx.json")
	if sbomFormat == internalsbom.FormatSPDX {
		sbomRaw = filepath.Join(baseDir, name+".sbom.spdx.json")
	}

	return outputPaths{
		BaseDir:             baseDir,
		Stem:                name,
		ProvenanceStatement: filepath.Join(baseDir, name+".provenance.json"),
		SBOMRaw:             sbomRaw,
		SBOMAttestation:     filepath.Join(baseDir, name+".sbom.att.json"),

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Fix permissions on the parent directory or run packer as a user with write access
  2. Correct the output path in the post-processor config so it is not blocked by an existing file
  3. Ensure the output path is inside a writable volume in containers/CI
  4. Free disk space if the failure was caused by a full disk

Example fix

// before
post-processor provenance {
  output = "/root/attestations"
}
// after
post-processor provenance {
  output = "./attestations"
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight in shell before packer build:
// mkdir -p "$OUTPUT_DIR" && test -w "$OUTPUT_DIR"
if err := os.MkdirAll(baseDir, 0755); err != nil {
    return fmt.Errorf("output dir not creatable: %w", err)
}

Try / catch

if err := pp.PostProcess(ctx, artifact); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) {
        // fix permissions / existing-file collision on pe.Path
    }
}

Prevention

When it happens

Trigger: PostProcess calls outputPaths; baseDir (derived from output path config or the working directory) cannot be created — permission denied, read-only filesystem, path segment is an existing file, or invalid path characters.

Common situations: Running packer in a read-only container FS; output directory path collides with an existing file; output path points outside a mounted volume; running as non-root writing to a privileged path.

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/c67c1baad209cbc4. Report an issue: GitHub.