router-for-me/CLIProxyAPI · error
private_key uses unsupported format
Error message
private_key uses unsupported format
What it means
Terminal failure of ensureRSAPrivateKey auto-detection: the PEM block has neither 'RSA PRIVATE KEY' nor 'PRIVATE KEY' as its type, and the fallback parses of block.Bytes as PKCS#1 and then PKCS#8 RSA both fail (keyutil.go:118-122). The key is in a format this normalizer cannot convert (e.g. EC, DSA, or a non-key PEM).
Source
Thrown at internal/auth/vertex/keyutil.go:122
if !ok {
return nil, fmt.Errorf("private_key is not an RSA key")
}
der := x509.MarshalPKCS1PrivateKey(rsaKey)
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: der}, nil
}
// Attempt auto-detection: try PKCS#1 first, then PKCS#8.
if rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
der := x509.MarshalPKCS1PrivateKey(rsaKey)
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: der}, nil
}
if key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {
if rsaKey, ok := key.(*rsa.PrivateKey); ok {
der := x509.MarshalPKCS1PrivateKey(rsaKey)
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: der}, nil
}
}
return nil, fmt.Errorf("private_key uses unsupported format")
}
func rebuildPEM(raw string) (string, error) {
kind := "PRIVATE KEY"
if strings.Contains(raw, "RSA PRIVATE KEY") {
kind = "RSA PRIVATE KEY"
}
header := "-----BEGIN " + kind + "-----"
footer := "-----END " + kind + "-----"
start := strings.Index(raw, header)
end := strings.Index(raw, footer)
if start < 0 || end <= start {
return "", fmt.Errorf("missing pem markers")
}
body := raw[start+len(header) : end]
payload := filterBase64(body)
if payload == "" {
return "", fmt.Errorf("private_key base64 payload empty")View on GitHub (pinned to 78f0c4079e)
Solutions
- Check the PEM label of the private_key value: it must be '-----BEGIN PRIVATE KEY-----' or '-----BEGIN RSA PRIVATE KEY-----'
- If it is a certificate or public key, replace it with the account's private key from the GCP JSON
- Convert OpenSSH keys if applicable: ssh-keygen -p -m pem -f key -N '' then ensure it is RSA
Example fix
# before "private_key": "-----BEGIN CERTIFICATE-----..." # after "private_key": "-----BEGIN PRIVATE KEY-----..."
Defensive patterns
Strategy: type-guard
Validate before calling
block, _ := pem.Decode([]byte(pk))
if block != nil && block.Type != "RSA PRIVATE KEY" && block.Type != "PRIVATE KEY" {
return fmt.Errorf("unsupported PEM type %q; expected a private key", block.Type)
} Type guard
func isSupportedPrivateKeyBlock(b *pem.Block) bool {
return b != nil && (b.Type == "RSA PRIVATE KEY" || b.Type == "PRIVATE KEY")
} Prevention
- Confirm the PEM label says PRIVATE KEY, not CERTIFICATE/PUBLIC KEY/OPENSSH
- Automate credential validation in CI with openssl
- Separate certificate and key stores to prevent mix-ups
When it happens
Trigger: private_key containing a CERTIFICATE, PUBLIC KEY, EC PRIVATE KEY, or DSA PEM block; an OpenSSH-format key ('OPENSSH PRIVATE KEY'); garbage bytes under an exotic PEM label.
Common situations: Pasting the wrong PEM (server certificate instead of the signing key) into the service account JSON; OpenSSH keys from ~/.ssh offered where an RSA PEM is required.
Related errors
- private_key is not valid pem: %w
- private_key pem decode failed
- missing pem markers
- service account missing private_key
- private_key invalid pkcs8: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/7e1f757ae26c2ba7.
Report an issue: GitHub.