slackhq/nebula · error
input did not contain a valid PEM encoded block
Error message
input did not contain a valid PEM encoded block
What it means
UnmarshalPublicKeyFromPEM calls pem.Decode on the input; if no valid PEM block can be parsed it returns this error. Only key-agreement (ECDH) public key PEM banners (X25519, P256) are accepted by this function once parsing succeeds.
Source
Thrown at cert/pem.go:157
// if your public key came from a certificate, prefer Certificate.PublicKeyPEM() if possible, to avoid mistakes!
func MarshalSigningPublicKeyToPEM(curve Curve, b []byte) []byte {
switch curve {
case Curve_CURVE25519:
return pem.EncodeToMemory(&pem.Block{Type: Ed25519PublicKeyBanner, Bytes: b})
case Curve_P256:
return pem.EncodeToMemory(&pem.Block{Type: ECDSAP256PublicKeyBanner, Bytes: b})
default:
return nil
}
}
// UnmarshalPublicKeyFromPEM will try to unmarshal the first pem block in a byte array, returning any non
// consumed data or an error on failure. Only key-agreement (ECDH) public key banners are accepted.
// Use UnmarshalSigningPublicKeyFromPEM for Ed25519/ECDSA banners.
func UnmarshalPublicKeyFromPEM(b []byte) ([]byte, []byte, Curve, error) {
k, r := pem.Decode(b)
if k == nil {
return nil, r, 0, fmt.Errorf("input did not contain a valid PEM encoded block")
}
var expectedLen int
var curve Curve
switch k.Type {
case X25519PublicKeyBanner:
expectedLen = 32
curve = Curve_CURVE25519
case P256PublicKeyBanner:
// Uncompressed
expectedLen = 65
curve = Curve_P256
default:
return nil, r, 0, fmt.Errorf("bytes did not contain a proper public key banner")
}
if len(k.Bytes) != expectedLen {
return nil, r, 0, fmt.Errorf("key was not %d bytes, is invalid %s public key", expectedLen, curve)
}
return k.Bytes, r, curve, nilView on GitHub (pinned to dd8f660c0a)
Solutions
- Ensure the input is PEM text starting with '-----BEGIN NEBULA X25519 PUBLIC KEY-----' or '-----BEGIN NEBULA ECDSA P256 PUBLIC KEY-----'
- If you have a signing (Ed25519/ECDSA) public key instead, call UnmarshalSigningPublicKeyFromPEM — but note that still requires PEM, so PEM-armor raw keys first
- Check the source of the bytes (file read error handling, HTTP response body) — the value may be empty or not what you expect
Example fix
// before
pub := rawKeyBytes // raw 32 bytes, no PEM
_, rest, curve, err := cert.UnmarshalPublicKeyFromPEM(pub)
// after
pemBytes := pem.EncodeToMemory(&pem.Block{Type: cert.X25519PublicKeyBanner, Bytes: rawKeyBytes})
_, rest, curve, err := cert.UnmarshalPublicKeyFromPEM(pemBytes) Defensive patterns
Strategy: validation
Validate before calling
func hasValidPEM(b []byte) bool {
blk, _ := pem.Decode(b)
return blk != nil
}
// guard: if !hasValidPEM(pubBytes) { return error before calling UnmarshalPublicKeyFromPEM } Type guard
func isECDHPublicKeyPEM(b []byte) bool {
blk, _ := pem.Decode(b)
if blk == nil {
return false
}
switch blk.Type {
case cert.X25519PublicKeyBanner, cert.P256PublicKeyBanner:
return len(blk.Bytes) == 32 || len(blk.Bytes) == 65
}
return false
} Try / catch
pub, rest, curve, err := cert.UnmarshalPublicKeyFromPEM(b)
if err != nil {
if strings.Contains(err.Error(), "valid PEM encoded block") {
return fmt.Errorf("public key input is not PEM-encoded; check the source of the bytes: %w", err)
}
return err
} Prevention
- Verify non-empty, PEM-formatted input (BEGIN line present) before parsing
- DER-encode vs PEM-encode: always use PEM for interchange with this library
- Check the bytes you actually read from files/env/HTTP before parsing
When it happens
Trigger: Calling UnmarshalPublicKeyFromPEM(b) where b contains no PEM block: empty bytes, raw key bytes, plain text, an invalid base64 body, or a certificate in DER (binary) form instead of PEM.
Common situations: Fetching a public key over HTTP and getting JSON/DER instead of PEM, env-var or template substitution leaving the value empty, passing raw ed25519.PublicKey bytes without PEM armor.
Related errors
- ErrTruncatedPEMBlock
- input did not contain a valid PEM encoded block
- bytes did not contain a proper public key banner
- key was not %d bytes, is invalid %s public key
- bytes did not contain a proper Ed25519/ECDSA public key bann
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/a82cc6379c424c28.
Report an issue: GitHub.