VictoriaMetrics/VictoriaMetrics · error
failed to parse key %q: failed to decode PEM block containin
Error message
failed to parse key %q: failed to decode PEM block containing public key
What it means
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).
Source
Thrown at lib/jwt/key.go:14
package jwt
import (
"crypto/x509"
"encoding/pem"
"fmt"
)
// ParseKey parses key in PEM format.
// It returns a *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, or ed25519.PublicKey.
func ParseKey(key []byte) (any, error) {
b, _ := pem.Decode(key)
if b == nil {
return nil, fmt.Errorf("failed to parse key %q: failed to decode PEM block containing public key", key)
}
k, err := x509.ParsePKIXPublicKey(b.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse key %q: %w", key, err)
}
return k, nil
}
View on GitHub (pinned to 5079fb58f1)
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
Example fix
// before
key := []byte("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...") // raw base64
// after
key := []byte("-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkq...\n-----END PUBLIC KEY-----") Defensive patterns
Strategy: validation
Validate before calling
func looksLikePEM(key []byte) bool {
b, _ := pem.Decode(key)
return b != nil
}
// check before calling jwt.ParseKey Type guard
func isDecodablePEM(key []byte) (*pem.Block, bool) {
b, _ := pem.Decode(key)
if b == nil || b.Type != "PUBLIC KEY" {
return nil, false
}
return b, true
} Try / catch
pub, err := jwt.ParseKey(keyBytes)
if err != nil {
if strings.Contains(err.Error(), "failed to decode PEM block") {
return fmt.Errorf("public key material is not PEM-encoded: %w", err)
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse key %q: %w
- algorithm is not supported
- cannot parse value match re=%q: %w
- key is nil
- key is not valid
AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03).
Data as JSON: /api/errors/de90b5d8458c8572.
Report an issue: GitHub.