hashicorp/packer · error

write Sigstore bundle %q: %w

Error message

write Sigstore bundle %q: %w

What it means

Wraps a failure from atomicWriteFile when persisting the generated Sigstore bundle next to the attestation file. The bundle path could not be written (bad directory, permissions, disk full). The underlying OS error is preserved via %w.

Source

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

		envelope = internalattestation.NewEnvelope(internalattestation.InTotoPayloadType, payload, signature)
	}

	if err := internalattestation.VerifyEnvelope(ctx, envelope, verifier); err != nil {
		return fmt.Errorf("verify signed attestation: %w", err)
	}

	output, err := json.MarshalIndent(envelope, "", "  ")
	if err != nil {
		return fmt.Errorf("marshal signed envelope: %w", err)
	}

	if err := atomicWriteFile(outputPath, output, 0664); err != nil {
		return fmt.Errorf("write attestation %q: %w", outputPath, err)
	}

	if len(bundleJSON) > 0 {
		if err := atomicWriteFile(bundlePath, bundleJSON, 0664); err != nil {
			return fmt.Errorf("write Sigstore bundle %q: %w", bundlePath, err)
		}
		ui.Say(fmt.Sprintf("Wrote Sigstore bundle to %s", bundlePath))
	}

	ui.Say(fmt.Sprintf("Wrote attestation to %s", outputPath))
	return nil
}

func (p *PostProcessor) signingResources(ctx context.Context, backendConfig internalattestation.BackendConfig) (internalattestation.Signer, internalattestation.Verifier, error) {
	if p.signingResourcesFn != nil {
		return p.signingResourcesFn(ctx, backendConfig)
	}

	if backendConfig.Mode == internalattestation.SigningModeNone {
		return nil, nil, nil
	}

	signer, err := internalattestation.NewSigner(ctx, backendConfig)

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Ensure the directory containing the bundle path exists before running packer (mkdir -p).
  2. Check filesystem permissions/write access for the user running packer (file mode is 0664).
  3. Free disk space or fix quota limits.
  4. Verify the bundle path derived from your output_path config is a writable file path, not a directory.
  5. If on a read-only volume, redirect output_path to a writable location.

Example fix

// before
"output_path": "/proc/attestation.json"
// after
"output_path": "./out/attestation.json"
Defensive patterns

Strategy: validation

Validate before calling

import os
func ensureWritableDir(path string) error {
	dir := filepath.Dir(path)
	if st, err := os.Stat(dir); err != nil {
		return fmt.Errorf("dir %s missing: %w", dir, err)
	} else if !st.IsDir() {
		return fmt.Errorf("%s is not a directory", dir)
	}
	f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0664)
	if err != nil { return err }
	return f.Close()
}
// call ensureWritableDir(bundlePath) before configuring output_path

Try / catch

if err := p.PostProcess(ctx, ...); err != nil {
	var pe *os.PathError
	if errors.As(err, &pe) {
		log.Printf("bundle write failed at %s: %v", pe.Path, pe.Err)
	}
	return err
}

Prevention

When it happens

Trigger: writeAttestation (called from PostProcess or writeSBOMAttestation) runs when len(bundleJSON) > 0 and atomicWriteFile(bundlePath, bundleJSON, 0664) returns a non-nil error.

Common situations: output_path directory does not exist or is not writable; disk quota exceeded; bundlePath points at a read-only mount or a directory instead of a file; permission denied under a restrictive umask or non-root CI user.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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