{"record":{"id":"e21c05766a6141f9","repo":"router-for-me/CLIProxyAPI","slug":"client-key-pem-type-q-is-unsupported","errorCode":null,"errorMessage":"client key pem type %q is unsupported","messagePattern":"client key pem type %q is unsupported","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/home/certificate.go","lineNumber":280,"sourceCode":"\tblock, _ := pem.Decode(raw)\n\tif block == nil {\n\t\treturn nil, fmt.Errorf(\"client key pem is invalid\")\n\t}\n\tswitch block.Type {\n\tcase \"RSA PRIVATE KEY\":\n\t\treturn x509.ParsePKCS1PrivateKey(block.Bytes)\n\tcase \"PRIVATE KEY\":\n\t\tkey, errParse := x509.ParsePKCS8PrivateKey(block.Bytes)\n\t\tif errParse != nil {\n\t\t\treturn nil, errParse\n\t\t}\n\t\trsaKey, ok := key.(*rsa.PrivateKey)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"client key is not rsa\")\n\t\t}\n\t\treturn rsaKey, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"client key pem type %q is unsupported\", block.Type)\n\t}\n}\n\nfunc createClientCSR(certificateID string, key *rsa.PrivateKey) ([]byte, error) {\n\tcertificateID = strings.TrimSpace(certificateID)\n\tif certificateID == \"\" {\n\t\treturn nil, fmt.Errorf(\"certificate id is required\")\n\t}\n\ttemplate := &x509.CertificateRequest{\n\t\tSubject: pkix.Name{\n\t\t\tCommonName: certificateID,\n\t\t},\n\t}\n\tder, errCreate := x509.CreateCertificateRequest(rand.Reader, template, key)\n\tif errCreate != nil {\n\t\treturn nil, errCreate\n\t}\n\treturn pem.EncodeToMemory(&pem.Block{Type: \"CERTIFICATE REQUEST\", Bytes: der}), nil","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/home/certificate.go#L262-L298","documentation":"Returned by parseRSAPrivateKeyPEM in internal/home/certificate.go for a PEM block whose type is neither 'RSA PRIVATE KEY' (PKCS#1) nor 'PRIVATE KEY' (PKCS#8). The %q verb includes the actual block type, e.g. 'EC PRIVATE KEY' (SEC1) or 'ENCRYPTED PRIVATE KEY' (PKCS#8 encrypted).","triggerScenarios":"Supplying an SEC1 EC key ('EC PRIVATE KEY'), an encrypted PKCS#8 key ('ENCRYPTED PRIVATE KEY'), or an unrelated PEM block (certificate, public key) as the client key.","commonSituations":"Key generated with openssl ec without converting to PKCS#8; passphrase-protected key exported from a browser or PKI tool; public key or certificate file mistakenly referenced by the client-key config field.","solutions":["Read the quoted block type in the error: 'EC PRIVATE KEY' means wrong algorithm — regenerate with openssl genrsa; 'ENCRYPTED PRIVATE KEY' means decrypt first: openssl pkcs8 -topk8 -nocrypt -in encrypted.key -out key.pem; a CERTIFICATE type means the config points at the wrong file","Regenerate the key as unencrypted RSA PEM and re-enroll"],"exampleFix":"# before (encrypted pkcs8)\nhome:\n  client-key: /etc/cliproxy/encrypted.key\n\n# after\nopenssl pkcs8 -topk8 -nocrypt -in /etc/cliproxy/encrypted.key -out /etc/cliproxy/client.key\nhome:\n  client-key: /etc/cliproxy/client.key","handlingStrategy":"validation","validationCode":"block, _ := pem.Decode(raw)\nswitch block.Type {\ncase \"RSA PRIVATE KEY\", \"PRIVATE KEY\": // ok\ncase \"ENCRYPTED PRIVATE KEY\":\n    return errors.New(\"client key is passphrase-protected; decrypt with: openssl pkcs8 -topk8 -nocrypt\")\ncase \"EC PRIVATE KEY\":\n    return errors.New(\"client key is EC; regenerate with: openssl genrsa -out client.key 2048\")\ndefault:\n    return fmt.Errorf(\"client key PEM type %q unusable\", block.Type)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize all client keys to unencrypted PKCS#8 RSA PEM at provisioning time","Keep certificates, keys, and CSRs in clearly named files (client.key, client.pem, ca.pem)"],"tags":["go","tls","private-key","pem","home"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}