router-for-me/CLIProxyAPI · error
client key pem is invalid
Error message
client key pem is invalid
What it means
Returned by parseRSAPrivateKeyPEM in internal/home/certificate.go when pem.Decode returns nil for the client key bytes — the file is not PEM at all. The enrollment/client-cert path requires an RSA private key in PEM form (PKCS#1 'RSA PRIVATE KEY' or PKCS#8 'PRIVATE KEY').
Source
Thrown at internal/home/certificate.go:264
if errWrite := os.WriteFile(path, raw, 0o600); errWrite != nil {
return errWrite
}
return os.Chmod(path, 0o600)
}
func chmodCertificateFiles(paths certificatePaths) error {
for _, path := range []string{paths.ClientCert, paths.ClientKey, paths.CACert} {
if errChmod := os.Chmod(path, 0o600); errChmod != nil {
return errChmod
}
}
return nil
}
func parseRSAPrivateKeyPEM(raw []byte) (*rsa.PrivateKey, error) {
block, _ := pem.Decode(raw)
if block == nil {
return nil, fmt.Errorf("client key pem is invalid")
}
switch block.Type {
case "RSA PRIVATE KEY":
return x509.ParsePKCS1PrivateKey(block.Bytes)
case "PRIVATE KEY":
key, errParse := x509.ParsePKCS8PrivateKey(block.Bytes)
if errParse != nil {
return nil, errParse
}
rsaKey, ok := key.(*rsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("client key is not rsa")
}
return rsaKey, nil
default:
return nil, fmt.Errorf("client key pem type %q is unsupported", block.Type)
}
}View on GitHub (pinned to 78f0c4079e)
Solutions
- Check the first line is -----BEGIN ... PRIVATE KEY----- (RSA PRIVATE KEY or PRIVATE KEY)
- If the key is DER, convert: openssl rsa -in key.der -inform DER -out key.pem
- Re-run enrollment to regenerate the client key pair if the original is lost
Example fix
# before home: client-key: /etc/cliproxy/client.key.der # after openssl rsa -in /etc/cliproxy/client.key.der -inform DER -out /etc/cliproxy/client.key home: client-key: /etc/cliproxy/client.key
Defensive patterns
Strategy: validation
Validate before calling
if raw, err := os.ReadFile(cfg.ClientKey); err != nil {
return fmt.Errorf("client key unreadable: %w", err)
} else if _, ok := pem.Decode(raw); !ok {
return fmt.Errorf("client key %s is not PEM encoded", cfg.ClientKey)
} Prevention
- Checksum-verify provisioned key files during deployment
- Never hand-edit or re-encode key files; copy bytes verbatim
When it happens
Trigger: Client key path points to a non-PEM file: a DER key, a JSON/seed file, an empty file, or a placeholder created by touch; key file truncated during provisioning.
Common situations: Provisioning script wrote the key in the wrong format; key downloaded via a channel that mangled it (HTML-escaped, base64-not-decoded); container secret mounted incorrectly leaving an empty file; file saved with a BOM.
Related errors
- client key pem type %q is unsupported
- home ca certificate pem is invalid
- client key is not rsa
- home tls: load client certificate: %w
- home tls: ca-cert contains no PEM certificates
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/b403748efee8d457.
Report an issue: GitHub.