{"record":{"id":"a82cc6379c424c28","repo":"slackhq/nebula","slug":"input-did-not-contain-a-valid-pem-encoded-block-a82cc6","errorCode":null,"errorMessage":"input did not contain a valid PEM encoded block","messagePattern":"input did not contain a valid PEM encoded block","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/pem.go","lineNumber":157,"sourceCode":"// if your public key came from a certificate, prefer Certificate.PublicKeyPEM() if possible, to avoid mistakes!\nfunc MarshalSigningPublicKeyToPEM(curve Curve, b []byte) []byte {\n\tswitch curve {\n\tcase Curve_CURVE25519:\n\t\treturn pem.EncodeToMemory(&pem.Block{Type: Ed25519PublicKeyBanner, Bytes: b})\n\tcase Curve_P256:\n\t\treturn pem.EncodeToMemory(&pem.Block{Type: ECDSAP256PublicKeyBanner, Bytes: b})\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// UnmarshalPublicKeyFromPEM will try to unmarshal the first pem block in a byte array, returning any non\n// consumed data or an error on failure. Only key-agreement (ECDH) public key banners are accepted.\n// Use UnmarshalSigningPublicKeyFromPEM for Ed25519/ECDSA banners.\nfunc UnmarshalPublicKeyFromPEM(b []byte) ([]byte, []byte, Curve, error) {\n\tk, r := pem.Decode(b)\n\tif k == nil {\n\t\treturn nil, r, 0, fmt.Errorf(\"input did not contain a valid PEM encoded block\")\n\t}\n\tvar expectedLen int\n\tvar curve Curve\n\tswitch k.Type {\n\tcase X25519PublicKeyBanner:\n\t\texpectedLen = 32\n\t\tcurve = Curve_CURVE25519\n\tcase P256PublicKeyBanner:\n\t\t// Uncompressed\n\t\texpectedLen = 65\n\t\tcurve = Curve_P256\n\tdefault:\n\t\treturn nil, r, 0, fmt.Errorf(\"bytes did not contain a proper public key banner\")\n\t}\n\tif len(k.Bytes) != expectedLen {\n\t\treturn nil, r, 0, fmt.Errorf(\"key was not %d bytes, is invalid %s public key\", expectedLen, curve)\n\t}\n\treturn k.Bytes, r, curve, nil","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/pem.go#L139-L175","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\npub := rawKeyBytes // raw 32 bytes, no PEM\n_, rest, curve, err := cert.UnmarshalPublicKeyFromPEM(pub)\n// after\npemBytes := pem.EncodeToMemory(&pem.Block{Type: cert.X25519PublicKeyBanner, Bytes: rawKeyBytes})\n_, rest, curve, err := cert.UnmarshalPublicKeyFromPEM(pemBytes)","handlingStrategy":"validation","validationCode":"func hasValidPEM(b []byte) bool {\n\tblk, _ := pem.Decode(b)\n\treturn blk != nil\n}\n// guard: if !hasValidPEM(pubBytes) { return error before calling UnmarshalPublicKeyFromPEM }","typeGuard":"func isECDHPublicKeyPEM(b []byte) bool {\n\tblk, _ := pem.Decode(b)\n\tif blk == nil {\n\t\treturn false\n\t}\n\tswitch blk.Type {\n\tcase cert.X25519PublicKeyBanner, cert.P256PublicKeyBanner:\n\t\treturn len(blk.Bytes) == 32 || len(blk.Bytes) == 65\n\t}\n\treturn false\n}","tryCatchPattern":"pub, rest, curve, err := cert.UnmarshalPublicKeyFromPEM(b)\nif err != nil {\n\tif strings.Contains(err.Error(), \"valid PEM encoded block\") {\n\t\treturn fmt.Errorf(\"public key input is not PEM-encoded; check the source of the bytes: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["pem","parsing","public-key","go"],"backgroundTag":"invalid-pem-block","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}