{"record":{"id":"d582036c546bae60","repo":"slackhq/nebula","slug":"input-did-not-contain-a-valid-pem-encoded-block","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/crypto.go","lineNumber":260,"sourceCode":"\n\treturn &Argon2Parameters{\n\t\tversion:     params.Version,\n\t\tMemory:      params.Memory,\n\t\tParallelism: uint8(params.Parallelism),\n\t\tIterations:  params.Iterations,\n\t\tsalt:        params.Salt,\n\t}, nil\n\n}\n\n// DecryptAndUnmarshalSigningPrivateKey will try to pem decode and decrypt an Ed25519/ECDSA private key with\n// the given passphrase, returning any other bytes b or an error on failure\nfunc DecryptAndUnmarshalSigningPrivateKey(passphrase, b []byte) (Curve, []byte, []byte, error) {\n\tvar curve Curve\n\n\tk, r := pem.Decode(b)\n\tif k == nil {\n\t\treturn curve, nil, r, fmt.Errorf(\"input did not contain a valid PEM encoded block\")\n\t}\n\n\tswitch k.Type {\n\tcase EncryptedEd25519PrivateKeyBanner:\n\t\tcurve = Curve_CURVE25519\n\tcase EncryptedECDSAP256PrivateKeyBanner:\n\t\tcurve = Curve_P256\n\tdefault:\n\t\treturn curve, nil, r, fmt.Errorf(\"bytes did not contain a proper nebula encrypted Ed25519/ECDSA private key banner\")\n\t}\n\n\tned, err := UnmarshalNebulaEncryptedData(k.Bytes)\n\tif err != nil {\n\t\treturn curve, nil, r, err\n\t}\n\n\tvar bytes []byte\n\tswitch ned.EncryptionMetadata.EncryptionAlgorithm {","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/crypto.go#L242-L278","documentation":"DecryptAndUnmarshalSigningPrivateKey calls pem.Decode on the input bytes; when no valid PEM block can be parsed (pem.Decode returns nil), it returns this error. The library requires the input to start with a PEM-encoded encrypted Nebula private key block. Any corrupted, truncated, or non-PEM input fails immediately before the key banner is even checked.","triggerScenarios":"Calling DecryptAndUnmarshalSigningPrivateKey(passphrase, b) where b is not parseable as PEM: empty input, plain-text key material, a passphrase typed instead of the key file, a PEM block with invalid base64 or missing BEGIN/END lines, or output of a different function (e.g. a certificate) passed by mistake.","commonSituations":"Config files pointing at the wrong file (config vs key file), key files mangled by copy/paste or secret-manager templating that produced empty content, Windows line-ending or whitespace corruption, or passing an unencrypted PEM (e.g. from OpenSSL) instead of a Nebula encrypted key produced by EncryptAndMarshalSigningPrivateKey.","solutions":["Verify the input bytes actually contain a PEM block starting with '-----BEGIN NEBULA ED25519 ENCRYPTED PRIVATE KEY-----' (or the ECDSA P256 equivalent) and are not empty","Check you are passing the encrypted private key file, not the certificate, CA file, or config file","If the file was produced by EncryptAndMarshalSigningPrivateKey, re-export/re-copy it without text-mangling (binary/base64-safe transfer)","Regenerate the key with nebula-cert if the source file is truly corrupt"],"exampleFix":"// before\nb, _ := os.ReadFile(\"config.yaml\") // wrong file\nk, _, _, err := cert.DecryptAndUnmarshalSigningPrivateKey(pass, b)\n// after\nb, _ := os.ReadFile(\"host.key\") // the encrypted Nebula private key\nk, _, _, err := cert.DecryptAndUnmarshalSigningPrivateKey(pass, b)","handlingStrategy":"validation","validationCode":"func hasPEM(b []byte) bool {\n\tblk, _ := pem.Decode(b)\n\treturn blk != nil\n}\n// call only if hasPEM(keyBytes)","typeGuard":"func isValidEncryptedSigningKeyPEM(b []byte) bool {\n\tblk, _ := pem.Decode(b)\n\tif blk == nil {\n\t\treturn false\n\t}\n\treturn blk.Type == cert.EncryptedEd25519PrivateKeyBanner || blk.Type == cert.EncryptedECDSAP256PrivateKeyBanner\n}","tryCatchPattern":"curve, key, rest, err := cert.DecryptAndUnmarshalSigningPrivateKey(pass, b)\nif err != nil {\n\tif strings.Contains(err.Error(), \"valid PEM encoded block\") {\n\t\treturn fmt.Errorf(\"key file is not PEM-encoded; check file path and contents: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Log/inspect the first line of the key file before decrypting to confirm it is PEM","Keep encrypted key files out of templating systems that may substitute empty values","Transfer key files in a binary-safe way (no clipboard copy/paste)","Write a startup check that validates all key files parse as PEM with expected banners"],"tags":["pem","parsing","key-management","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"}