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
- Verify the path exists with os.Stat or ls and correct typos
- Use an absolute path or run from the directory you expect
- Check file read permissions for the invoking user
- 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
- Stat the attestation path before verification
- Use absolute paths derived from the artifact output directory
- Ensure the signing step completes (and uploads the file) before verification in CI
- Check file permissions after artifact transfer
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
- failed to open %s: %s
- failed to read %s: %s
- unable to compute %s hash for %s
- write attestation %q: %w
- write Sigstore bundle %q: %w
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/6283a36eff7c9c12.
Report an issue: GitHub.