{"record":{"id":"7e1f757ae26c2ba7","repo":"router-for-me/CLIProxyAPI","slug":"private-key-uses-unsupported-format","errorCode":null,"errorMessage":"private_key uses unsupported format","messagePattern":"private_key uses unsupported format","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/auth/vertex/keyutil.go","lineNumber":122,"sourceCode":"\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"private_key is not an RSA key\")\n\t\t}\n\t\tder := x509.MarshalPKCS1PrivateKey(rsaKey)\n\t\treturn &pem.Block{Type: \"RSA PRIVATE KEY\", Bytes: der}, nil\n\t}\n\n\t// Attempt auto-detection: try PKCS#1 first, then PKCS#8.\n\tif rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {\n\t\tder := x509.MarshalPKCS1PrivateKey(rsaKey)\n\t\treturn &pem.Block{Type: \"RSA PRIVATE KEY\", Bytes: der}, nil\n\t}\n\tif key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {\n\t\tif rsaKey, ok := key.(*rsa.PrivateKey); ok {\n\t\t\tder := x509.MarshalPKCS1PrivateKey(rsaKey)\n\t\t\treturn &pem.Block{Type: \"RSA PRIVATE KEY\", Bytes: der}, nil\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"private_key uses unsupported format\")\n}\n\nfunc rebuildPEM(raw string) (string, error) {\n\tkind := \"PRIVATE KEY\"\n\tif strings.Contains(raw, \"RSA PRIVATE KEY\") {\n\t\tkind = \"RSA PRIVATE KEY\"\n\t}\n\theader := \"-----BEGIN \" + kind + \"-----\"\n\tfooter := \"-----END \" + kind + \"-----\"\n\tstart := strings.Index(raw, header)\n\tend := strings.Index(raw, footer)\n\tif start < 0 || end <= start {\n\t\treturn \"\", fmt.Errorf(\"missing pem markers\")\n\t}\n\tbody := raw[start+len(header) : end]\n\tpayload := filterBase64(body)\n\tif payload == \"\" {\n\t\treturn \"\", fmt.Errorf(\"private_key base64 payload empty\")","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/vertex/keyutil.go#L104-L140","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\n\"private_key\": \"-----BEGIN CERTIFICATE-----...\"\n# after\n\"private_key\": \"-----BEGIN PRIVATE KEY-----...\"","handlingStrategy":"type-guard","validationCode":"block, _ := pem.Decode([]byte(pk))\nif block != nil && block.Type != \"RSA PRIVATE KEY\" && block.Type != \"PRIVATE KEY\" {\n    return fmt.Errorf(\"unsupported PEM type %q; expected a private key\", block.Type)\n}","typeGuard":"func isSupportedPrivateKeyBlock(b *pem.Block) bool {\n    return b != nil && (b.Type == \"RSA PRIVATE KEY\" || b.Type == \"PRIVATE KEY\")\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["vertex","pem","unsupported-format","private-key"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}