hashicorp/packer · error

no PEM block found

Error message

no PEM block found

What it means

loadPEMPublicKey (used by LoadPEMVerifier and LoadPEMVerifierBytes) found no PEM block: pem.Decode returned nil because the byte slice lacks valid '-----BEGIN/END-----' armor. This is the inner error normally surfaced to callers wrapped as 'load verifier %q: %w'.

Source

Thrown at internal/attestation/sign_key.go:176

	}

	publicKeyPEM, err := marshalPublicKeyPEM(signer.Public())
	if err != nil {
		return nil, nil, err
	}

	verifier, err := LoadPEMVerifierBytes(publicKeyPEM)
	if err != nil {
		return nil, nil, err
	}

	return signer, verifier, nil
}

func loadPEMPublicKey(contents []byte) (crypto.PublicKey, []byte, error) {
	block, _ := pem.Decode(contents)
	if block == nil {
		return nil, nil, fmt.Errorf("no PEM block found")
	}

	if publicKey, err := x509.ParsePKIXPublicKey(block.Bytes); err == nil {
		return publicKey, pem.EncodeToMemory(block), nil
	}
	if certificate, err := x509.ParseCertificate(block.Bytes); err == nil {
		return certificate.PublicKey, pem.EncodeToMemory(block), nil
	}
	if privateKey, verifier, err := loadPEMPrivateKeyAsPublic(contents); err == nil {
		return privateKey, verifier, nil
	}

	return nil, nil, fmt.Errorf("unsupported PEM verifier data")
}

func loadPEMPrivateKeyAsPublic(contents []byte) (crypto.PublicKey, []byte, error) {
	block, _ := pem.Decode(contents)
	if block == nil {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Ensure the content includes PEM armor ('-----BEGIN PUBLIC KEY-----' or '-----BEGIN CERTIFICATE-----').
  2. Convert DER to PEM: 'openssl x509 -inform DER -in cert.der -out cert.pem' or 'openssl pkey -pubin -inform DER -pubout'.
  3. If content is fetched at runtime, log its first line to confirm armor is present before calling the loader.
  4. Prefer LoadPEMVerifierBytes in tests with known-good PEM to isolate format from path issues.

Example fix

// before
der, _ := os.ReadFile("cert.der")
v, err := attestation.LoadPEMVerifierBytes(der) // no PEM block found
// after
pemBytes, _ := os.ReadFile("cert.pem") // -----BEGIN CERTIFICATE-----
v, err := attestation.LoadPEMVerifierBytes(pemBytes)
Defensive patterns

Strategy: validation

Validate before calling

func hasPEM(content []byte) error {
	if len(bytes.TrimSpace(content)) == 0 {
		return errors.New("verifier content is empty")
	}
	if block, _ := pem.Decode(content); block == nil {
		return errors.New("verifier content has no PEM armor (BEGIN/END lines missing)")
	}
	return nil
}

Type guard

func isPEMEncoded(b []byte) bool {
	block, _ := pem.Decode(b)
	return block != nil
}

Try / catch

v, err := attestation.LoadPEMVerifierBytes(content)
if err != nil && strings.Contains(err.Error(), "no PEM block found") {
	return fmt.Errorf("verifier bytes are not PEM; convert DER: openssl x509 -inform DER -pubout; first 32 bytes: %q", content[:min(32, len(content))])
}

Prevention

When it happens

Trigger: Calling LoadPEMVerifier or LoadPEMVerifierBytes with empty bytes, raw DER public-key bytes, plain base64, or text with a malformed PEM header.

Common situations: Embedding a raw DER certificate in config; a fetch script that wrote binary content; copy-paste losing the BEGIN/END lines; reading the wrong file (e.g. a checksum or signature file).

Related errors


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