hashicorp/packer · error
decode signer %q: no PEM block found
Error message
decode signer %q: no PEM block found
What it means
loadPEMSigner read the file but pem.Decode returned nil, meaning the contents contain no valid PEM block at all. PEM requires the '-----BEGIN ...-----'/'-----END ...-----' ASCII armor; raw DER bytes, JSON, or an empty file all fail here. The message is static (not wrapped), so the path is included for identification only.
Source
Thrown at internal/attestation/sign_key.go:142
return nil, err
}
return &pemVerifier{
publicKey: publicKey,
keyID: sha256Hex(rawVerifier),
}, nil
}
func loadPEMSigner(path string) (crypto.Signer, *pemVerifier, error) {
contents, err := os.ReadFile(path)
if err != nil {
return nil, nil, fmt.Errorf("read signer %q: %w", path, err)
}
block, _ := pem.Decode(contents)
if block == nil {
return nil, nil, fmt.Errorf("decode signer %q: no PEM block found", path)
}
var signer crypto.Signer
if key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {
var ok bool
signer, ok = key.(crypto.Signer)
if !ok {
return nil, nil, fmt.Errorf("signer %q does not implement crypto.Signer", path)
}
} else if key, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
signer = key
} else if key, err := x509.ParseECPrivateKey(block.Bytes); err == nil {
signer = key
} else {
return nil, nil, fmt.Errorf("unsupported private key in signer %q", path)
}
publicKeyPEM, err := marshalPublicKeyPEM(signer.Public())View on GitHub (pinned to eb36e3c3e4)
Solutions
- Verify the file literally starts with '-----BEGIN' (head -1 key.pem); convert raw DER with 'openssl pkcs8 -inform DER -in key.der -out key.pem'.
- Re-export or re-download the key ensuring PEM (base64 armor) output.
- Check the file is not empty and was not truncated (compare byte size with the source).
- Call pem.Decode yourself in a pre-check to validate the file before invoking the signer.
Example fix
// before
$ openssl pkcs8 -topk8 -in key.pem -outform DER -out key.der // no armor
signer, _, err := attestation.NewSigner("key.der") // no PEM block found
// after
$ openssl pkcs8 -topk8 -in key.pem -out key.pem.new // PEM armor kept
signer, _, err := attestation.NewSigner("key.pem.new") Defensive patterns
Strategy: validation
Validate before calling
raw, err := os.ReadFile(keyPath)
if err != nil {
return err
}
block, _ := pem.Decode(raw)
if block == nil {
return fmt.Errorf("%s: no PEM armor; expected -----BEGIN ... PRIVATE KEY-----", keyPath)
} Type guard
func isPEM(b []byte) bool {
block, _ := pem.Decode(b)
return block != nil
} Try / catch
signer, verifier, err := attestation.NewSigner(keyPath)
if err != nil && strings.Contains(err.Error(), "no PEM block found") {
return fmt.Errorf("%s must be PEM-encoded; convert DER with: openssl pkcs8 -inform DER -in key.der -out key.pem", keyPath)
} Prevention
- Always export keys with PEM output (avoid -outform DER for files consumed by this library).
- Check 'head -1 key.pem' shows '-----BEGIN' after every key transfer.
- Never paste base64 blobs into key files without the BEGIN/END armor lines.
- Verify file size/checksum after download or copy to catch truncation.
When it happens
Trigger: Calling newPEMSigner(path) with a file containing raw DER-encoded key bytes, base64 without armor lines, an empty file, or text where the BEGIN line is malformed (e.g. wrong number of dashes or extra leading bytes before the header).
Common situations: Exported key with 'openssl pkcs8 -topk8 -outform DER'; base64 blob pasted into a file without armor; downloading a key through a tool that stripped newlines; truncated/corrupted file after a failed transfer.
Related errors
- read signer %q: %w
- no PEM block found
- signing_mode %q does not support Sigstore bundle emission
- read verifier %q: %w
- load verifier %q: %w
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/1ce27d7187fac6c6.
Report an issue: GitHub.