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

  1. Supply a full PEM block including -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- with intact newlines
  2. Convert the key to PEM: for raw base64 DER, wrap it in a PEM block with type 'PUBLIC KEY'
  3. 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

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

Related errors


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/de90b5d8458c8572. Report an issue: GitHub.