{"record":{"id":"60924dca10e3212c","repo":"router-for-me/CLIProxyAPI","slug":"private-key-base64-decode-failed-w","errorCode":null,"errorMessage":"private_key base64 decode failed: %w","messagePattern":"private_key base64 decode failed: %w","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/auth/vertex/keyutil.go","lineNumber":144,"sourceCode":"\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\")\n\t}\n\tder, err := base64.StdEncoding.DecodeString(payload)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"private_key base64 decode failed: %w\", err)\n\t}\n\tblock := &pem.Block{Type: kind, Bytes: der}\n\treturn string(pem.EncodeToMemory(block)), nil\n}\n\nfunc filterBase64(s string) string {\n\tvar b strings.Builder\n\tfor _, r := range s {\n\t\tswitch {\n\t\tcase r >= 'A' && r <= 'Z':\n\t\t\tb.WriteRune(r)\n\t\tcase r >= 'a' && r <= 'z':\n\t\t\tb.WriteRune(r)\n\t\tcase r >= '0' && r <= '9':\n\t\t\tb.WriteRune(r)\n\t\tcase r == '+' || r == '/' || r == '=':\n\t\t\tb.WriteRune(r)\n\t\tdefault:","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/vertex/keyutil.go#L126-L162","documentation":"From rebuildPEM when the extracted base64 payload (after filtering to the standard alphabet) fails base64.StdEncoding.DecodeString (keyutil.go:142-145). Even after removing whitespace and invalid characters, the remaining string is not valid base64 — typically wrong length/padding or mixed-in foreign characters that happen to be base64-legal but break the structure.","triggerScenarios":"Base64 body with characters dropped or duplicated mid-key (still alphanumeric, so filterBase64 keeps them, but length/mod-4 is broken); padding '=' stripped; concatenated fragments of two different keys.","commonSituations":"Manual copy-paste that misses or duplicates a line of the base64; terminals wrapping lines into the value; sed/awk processing that deletes characters.","solutions":["Re-copy the key from the source JSON in one shot, or re-download it from GCP","Sanity-check length and padding: the base64 body length mod 4 must be 0 (ignoring final '=' padding)","Avoid line-based shell edits on the private_key value"],"exampleFix":"# validate independently before feeding the proxy\njq -r .private_key sa.json | sed '1d;$d' | tr -d '\\n' | base64 -d >/dev/null && echo OK || echo CORRUPT","handlingStrategy":"validation","validationCode":"body := filterBase64(pkBetweenMarkers(pk))\nif _, err := base64.StdEncoding.DecodeString(body); err != nil {\n    return fmt.Errorf(\"PEM base64 body corrupt: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy keys in one action; avoid line-by-line selection","Compare checksums after transferring key material","Re-download rather than hand-fix corrupt base64"],"tags":["vertex","base64","pem","corruption"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}