hashicorp/packer · error

read verifier %q: %w

Error message

read verifier %q: %w

What it means

LoadPEMVerifier failed to read the verifier file at the given path because os.ReadFile returned an error. The library wraps the underlying OS error (e.g. *fs.PathError with ENOENT, EACCES) so the cause is preserved via errors.Unwrap. This is a file-access problem, not a key-content problem.

Source

Thrown at internal/attestation/sign_key.go:107

		return nil
	case ed25519.PublicKey:
		if !ed25519.Verify(publicKey, pae, signature) {
			return fmt.Errorf("Ed25519 verification failed")
		}
		return nil
	default:
		return fmt.Errorf("unsupported public key type %T", v.publicKey)
	}
}

func (v *pemVerifier) KeyID() string {
	return v.keyID
}

func LoadPEMVerifier(path string) (Verifier, error) {
	contents, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("read verifier %q: %w", path, err)
	}

	publicKey, rawVerifier, err := loadPEMPublicKey(contents)
	if err != nil {
		return nil, fmt.Errorf("load verifier %q: %w", path, err)
	}

	return &pemVerifier{
		publicKey: publicKey,
		keyID:     sha256Hex(rawVerifier),
	}, nil
}

func LoadPEMVerifierBytes(contents []byte) (*pemVerifier, error) {
	publicKey, rawVerifier, err := loadPEMPublicKey(contents)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Verify the path exists with os.Stat / 'ls -l <path>' and fix typos in the configured path.
  2. Check file permissions and the effective user (chmod/chown or run as a user with read access).
  3. If using a relative path, switch to an absolute path or fix the process working directory.
  4. Inspect the wrapped error with errors.Unwrap or errors.Is(err, fs.ErrNotExist) to identify the exact OS-level cause.

Example fix

// before
v, err := attestation.LoadPEMVerifier("verifier.pem") // fails: file not found
// after
if _, err := os.Stat("/etc/packer/verifier.pem"); err != nil {
	log.Fatal(err)
}
v, err := attestation.LoadPEMVerifier("/etc/packer/verifier.pem")
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(path)
if err != nil {
	return fmt.Errorf("verifier file %q unavailable: %w", path, err)
}
if info.IsDir() {
	return fmt.Errorf("verifier path %q is a directory", path)
}
f, err := os.Open(path)
if err != nil {
	return fmt.Errorf("verifier file %q not readable: %w", path, err)
}
f.Close()

Try / catch

v, err := attestation.LoadPEMVerifier(path)
if err != nil {
	if errors.Is(err, fs.ErrNotExist) {
		return fmt.Errorf("verifier file missing at %s", path)
	}
	if errors.Is(err, fs.ErrPermission) {
		return fmt.Errorf("verifier file %s not readable by this user", path)
	}
	return err
}

Prevention

When it happens

Trigger: Calling LoadPEMVerifier(path) or any caller (NewVerifier, verifierForEnvelope) with a path that does not exist, is a directory, has too-restrictive permissions, or sits on an unavailable mount.

Common situations: Typo in the verifier path in config; file deleted or never provisioned; running the binary as a different user than the key owner; container image missing the mounted key; relative path resolved against an unexpected working directory.

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