{"record":{"id":"de90b5d8458c8572","repo":"VictoriaMetrics/VictoriaMetrics","slug":"failed-to-parse-key-q-failed-to-decode-pem-block","errorCode":null,"errorMessage":"failed to parse key %q: failed to decode PEM block containing public key","messagePattern":"failed to parse key %q: failed to decode PEM block containing public key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/jwt/key.go","lineNumber":14,"sourceCode":"package jwt\n\nimport (\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"fmt\"\n)\n\n// ParseKey parses key in PEM format.\n// It returns a *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, or ed25519.PublicKey.\nfunc ParseKey(key []byte) (any, error) {\n\tb, _ := pem.Decode(key)\n\tif b == nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse key %q: failed to decode PEM block containing public key\", key)\n\t}\n\n\tk, err := x509.ParsePKIXPublicKey(b.Bytes)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse key %q: %w\", key, err)\n\t}\n\n\treturn k, nil\n}\n","sourceCodeStart":1,"sourceCodeEnd":24,"githubUrl":"https://github.com/VictoriaMetrics/VictoriaMetrics/blob/5079fb58f1e8e62113f90c945ad71586c797d770/lib/jwt/key.go#L1-L24","documentation":"ParseKey decodes a PEM block and fails when pem.Decode returns nil, meaning the input bytes do not contain a valid PEM-formatted public key at all. The literal key material is included in the message (possibly truncated by the caller's logging).","triggerScenarios":"Calling ParseKey with bytes that are not PEM: raw base64 DER, an OpenSSH 'ssh-rsa AAAA...' public key line, a bare hex key, an empty string, or PEM without the BEGIN/END headers.","commonSituations":"JWKS 'n'/'e' fields pasted directly instead of a full PEM; keys copied from an SSH authorized_keys file; config where the newlines of the PEM were collapsed/escaped so the header is mangled; env var trimming the BEGIN line.","solutions":["Supply a full PEM block including -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- with intact newlines","Convert the key to PEM: for raw base64 DER, wrap it in a PEM block with type 'PUBLIC KEY'","If the key is OpenSSH format, convert it (e.g. ssh-keygen -e -m PKCS8 or openssl) to SPKI PEM"],"exampleFix":"// before\nkey := []byte(\"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...\") // raw base64\n// after\nkey := []byte(\"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkq...\\n-----END PUBLIC KEY-----\")","handlingStrategy":"validation","validationCode":"func looksLikePEM(key []byte) bool {\n    b, _ := pem.Decode(key)\n    return b != nil\n}\n// check before calling jwt.ParseKey","typeGuard":"func isDecodablePEM(key []byte) (*pem.Block, bool) {\n    b, _ := pem.Decode(key)\n    if b == nil || b.Type != \"PUBLIC KEY\" {\n        return nil, false\n    }\n    return b, true\n}","tryCatchPattern":"pub, err := jwt.ParseKey(keyBytes)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to decode PEM block\") {\n        return fmt.Errorf(\"public key material is not PEM-encoded: %w\", err)\n    }\n    return err\n}","preventionTips":["Store keys as complete PEM files with BEGIN/END headers and real newlines","Never paste raw JWKS n/e values where PEM is expected","Convert OpenSSH keys to SPKI PEM before configuring","Log key fingerprints, not raw key material, when debugging"],"tags":["jwt","pem","public-key","configuration","go"],"backgroundTag":"invalid-pem-key-format","analyzedSha":"5079fb58f1e8e62113f90c945ad71586c797d770","analyzedAt":"2026-09-03T18:10:26.153Z","contentChangedAt":"2026-09-03T18:10:26.153Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}