hashicorp/packer · error

read attestation %q: %w

Error message

read attestation %q: %w

What it means

VerifyAttestationFile wraps the os.ReadFile failure for the attestation path in `read attestation %q: %w`. It means the file at the given path could not be opened or read — typically it does not exist, the path is wrong, or permissions deny access. The underlying OS error is preserved for diagnosis.

Source

Thrown at internal/attestation/verify.go:44

	SourceURI                string
	ArtifactPath             string
	SigstoreBundlePath       string
	RequireTransparencyLog   bool
	RequireObserverTimestamp bool
}

var loadSigstoreBundle = sigstorebundle.LoadJSONFromPath

var newSigstoreBundleVerifier = sigstoreverify.NewVerifier

var verifySigstoreBundleEvidence = func(envelope Envelope, cfg BackendConfig, policy VerificationPolicy) error {
	return verifySigstoreBundleEvidenceImpl(envelope, cfg, policy)
}

func VerifyAttestationFile(ctx context.Context, path string, cfg BackendConfig, policy VerificationPolicy) (*internalprovenance.Statement, error) {
	contents, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("read attestation %q: %w", path, err)
	}

	var envelope Envelope
	if err := json.Unmarshal(contents, &envelope); err != nil {
		return nil, fmt.Errorf("decode attestation envelope %q: %w", path, err)
	}

	if envelope.PayloadType != InTotoPayloadType {
		return nil, fmt.Errorf("attestation %q has unexpected payloadType %q (want %q)",
			path, envelope.PayloadType, InTotoPayloadType)
	}

	if err := verifyEnvelopeSignature(ctx, path, cfg, policy, envelope); err != nil {
		return nil, err
	}

	payload, err := DecodeEnvelopePayload(envelope)
	if err != nil {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Verify the path exists with os.Stat or ls and correct typos
  2. Use an absolute path or run from the directory you expect
  3. Check file read permissions for the invoking user
  4. Ensure the signing pipeline actually wrote the attestation before verification runs

Example fix

// before
stmt, err := attestation.VerifyAttestationFile(ctx, "attest.json", cfg, policy)

// after: check existence first
if _, err := os.Stat("dist/attest.json"); err != nil { log.Fatal(err) }
stmt, err := attestation.VerifyAttestationFile(ctx, "dist/attest.json", cfg, policy)
Defensive patterns

Strategy: validation

Validate before calling

if info, err := os.Stat(path); err != nil { return fmt.Errorf"attestation %s unavailable: %w", path, err) } else if info.IsDir() { return fmt.Errorf"%s is a directory", path) }

Try / catch

stmt, err := attestation.VerifyAttestationFile(ctx, path, cfg, policy)
if err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && errors.Is(err, fs.ErrNotExist) {
        return fmt.Errorf"attestation file missing at %s — did signing run?", path)
    }
    return err
}

Prevention

When it happens

Trigger: Calling VerifyAttestationFile(ctx, path, cfg, policy) with a path that does not exist, a directory instead of a file, a path with a typo, or a file the process lacks read permission for; running before the signing step produced the attestation.

Common situations: Relative vs absolute path confusion when invoking packer from a different working directory; attestation written to a different output directory than expected; CI artifact not downloaded/mounted; restrictive file modes after artifact upload.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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