{"record":{"id":"2d78bcdff9b92a21","repo":"hyperledger/fabric","slug":"failed-to-decode-pem-block-from-s","errorCode":null,"errorMessage":"failed to decode PEM block from %s","messagePattern":"failed to decode PEM block from (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/common/signer/signer.go","lineNumber":116,"sourceCode":"\t// Fabric only supports ECDSA and ed25519 at the moment.\n\tcase *ecdsa.PrivateKey:\n\t\tdigest := util.ComputeSHA256(msg)\n\t\treturn signECDSA(si.key.(*ecdsa.PrivateKey), digest)\n\tcase ed25519.PrivateKey:\n\t\treturn ed25519.Sign(si.key.(ed25519.PrivateKey), msg), nil\n\tdefault:\n\t\treturn nil, errors.Errorf(\"found unknown private key type (%T) in msg signing\", key)\n\t}\n}\n\nfunc loadPrivateKey(file string) (crypto.PrivateKey, error) {\n\tb, err := os.ReadFile(file)\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\tbl, _ := pem.Decode(b)\n\tif bl == nil {\n\t\treturn nil, errors.Errorf(\"failed to decode PEM block from %s\", file)\n\t}\n\tkey, err := parsePrivateKey(bl.Bytes)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn key, nil\n}\n\n// Based on crypto/tls/tls.go but modified for Fabric:\nfunc parsePrivateKey(der []byte) (crypto.PrivateKey, error) {\n\t// OpenSSL 1.0.0 generates PKCS#8 keys.\n\tif key, err := x509.ParsePKCS8PrivateKey(der); err == nil {\n\t\tswitch key := key.(type) {\n\t\t// Fabric only supports ECDSA at the moment.\n\t\tcase *ecdsa.PrivateKey:\n\t\t\treturn key, nil\n\t\tcase ed25519.PrivateKey:\n\t\t\treturn key, nil","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/cmd/common/signer/signer.go#L98-L134","documentation":"loadPrivateKey reads the key file and calls pem.Decode; if the file content is not a valid PEM block (nil result), it throws this error including the file path. The Signer requires the private key in PEM form to parse it via parsePrivateKey.","triggerScenarios":"NewSigner with a key file that is raw DER, empty, an error page, base64 without headers, or corrupted/truncated PEM; wrong path passed as SignerConfig.KeyPath so the file read succeeds but content isn't PEM.","commonSituations":"Key exported in DER (PKCS#8/SEC1 binary) form; key file truncated by failed download; pointing KeyPath at the certificate or some other non-PEM file; trailing whitespace-only file.","solutions":["Convert the key to PEM: openssl pkey -inform DER -in key.der -out key.pem (or openssl ec -in key.sec1.der ... )","Verify the file contains '-----BEGIN ... PRIVATE KEY-----' at the top","Fix SignerConfig.KeyPath in config to point at the actual PEM private key","Re-download/re-export the key from the MSP directory"],"exampleFix":"// before\nopenssl pkcs8 -topk8 -inform DER -in key.der -out key.pem -nocrypt\n// after: config signer.key: /path/to/key.pem (PEM-encoded)","handlingStrategy":"validation","validationCode":"b, _ := os.ReadFile(keyPath)\nif blk, _ := pem.Decode(b); blk == nil {\n    return fmt.Errorf(\"%s is not PEM-encoded\", keyPath)\n}","typeGuard":"func isPEMPrivateKey(b []byte) bool {\n    blk, _ := pem.Decode(b)\n    return blk != nil && strings.Contains(blk.Type, \"PRIVATE KEY\")\n}","tryCatchPattern":"s, err := signer.NewSigner(keyPath, idPath)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to decode PEM block\") {\n        return fmt.Errorf(\"key %s not PEM; convert: openssl pkey -inform DER\", keyPath)\n    }\n    return err\n}","preventionTips":["Convert DER keys to PEM at enrollment time","Check file starts with '-----BEGIN' before use","Verify KeyPath points to the key, not the cert"],"tags":["pem","private-key","fabric","validation"],"backgroundTag":"invalid-pem-private-key","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}