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

  1. Check the PEM label of the private_key value: it must be '-----BEGIN PRIVATE KEY-----' or '-----BEGIN RSA PRIVATE KEY-----'
  2. If it is a certificate or public key, replace it with the account's private key from the GCP JSON
  3. 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

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


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/7e1f757ae26c2ba7. Report an issue: GitHub.