router-for-me/CLIProxyAPI · error
private_key base64 payload empty
Error message
private_key base64 payload empty
What it means
From rebuildPEM after the BEGIN/END markers were located, but the text between them yields no base64 characters after filterBase64 strips whitespace and invalid characters (keyutil.go:137-141). The PEM envelope exists while the actual key payload is empty.
Source
Thrown at internal/auth/vertex/keyutil.go:140
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")
}
der, err := base64.StdEncoding.DecodeString(payload)
if err != nil {
return "", fmt.Errorf("private_key base64 decode failed: %w", err)
}
block := &pem.Block{Type: kind, Bytes: der}
return string(pem.EncodeToMemory(block)), nil
}
func filterBase64(s string) string {
var b strings.Builder
for _, r := range s {
switch {
case r >= 'A' && r <= 'Z':
b.WriteRune(r)
case r >= 'a' && r <= 'z':
b.WriteRune(r)
case r >= '0' && r <= '9':View on GitHub (pinned to 78f0c4079e)
Solutions
- Check that the secret value is not a placeholder; fetch the real key material from GCP
- Inspect the region between the BEGIN/END lines: jq -r .private_key sa.json | sed -n '2,3p' should show base64, not '***'
- Re-download and redeploy the unmodified service account JSON
Example fix
# before "private_key": "-----BEGIN PRIVATE KEY-----\n***REDACTED***\n-----END PRIVATE KEY-----" # after "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQ...(real base64)...\n-----END PRIVATE KEY-----"
Defensive patterns
Strategy: validation
Validate before calling
body := pkBetweenMarkers(pk)
if len(strings.Map(func(r rune) rune {
if isBase64Rune(r) { return r }
return -1
}, body)) == 0 {
return fmt.Errorf("PEM body contains no base64 key material (redacted?)")
} Prevention
- Ensure secret managers return real values, not placeholders, before deploy
- Scan credentials for redaction markers (***, <redacted>, null)
- Integration-test the auth path with the actual production secret
When it happens
Trigger: A PEM block containing only comments or an empty body; base64 body replaced by placeholder text like '<redacted>' or '***'; whitespace-only body between valid-looking markers.
Common situations: Sanitized/redacted credential templates deployed by mistake; secret managers substituting placeholders when access is denied; manual template editing that deletes the body but leaves headers.
Related errors
- private_key base64 decode failed: %w
- private_key is not valid pem: %w
- private_key pem decode failed
- private_key uses unsupported format
- missing pem markers
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/ea44ee4d57f6b6da.
Report an issue: GitHub.